【DFS】【樹】Candy選首都(treeland)

DescriptionDescription

Treeland是一個有n個城市組成的國家,其中一些城市之間有單向邊連通。在這個國家中一共有n-1條路。我們知道,如果我們不考慮路的方向,那麼我可以從任意城市到達任意城市。
最近,Treeland的總理Candy爲了發展經濟,想要從這n個城市中選擇一個作爲Treeland的首都,首都必須要能到達其他任意城市,這使得有些道路必須反向,付出的代價即需要反向的道路條數。
Candy想要選擇一個城市作爲首都,使得付出的代價最小。可能有多個城市滿足條件,按編號從小到大輸出。

InputInput

第一行,一個整數n,表示城市個數
接下來n-1行,每行兩個整數x、y,表示城市x到城市y之間有一條單向路徑

OutputOutput

第一行,一個整數k,花費的最小代價。
第二行若干個整數,中間用空格隔開,表示滿足條件的城市編號。行末沒有多餘的空格。

SampleSample InputInput

Sample Input1:
3
2 1
2 3

Sample Input2:
4
1 4
2 4
3 4

SampleSample OutputOutput

Sample Output1:
0
2

Sample Output2:
2
1 2 3

HintHint

對於70%的數據 n<=5000
對於100%的數據 n<=2*10^5

TrainTrain ofof ThoughtThought

存下一條邊改變和不改變的情況,然後對於一個點進行深搜,求出有多少條邊需要改變才能使其變爲一棵樹,然後再換根,繼續求就好了

CodeCode

#include<cstdio>
#include<iostream>
#include<algorithm>

using namespace std;
int ans, n, t;
int st[200005], h[200005], s[200005];
bool meet[200005];

struct Tree
{
	int to, next, change;
}tree[400005];

void dfs(int x)
{
	meet[x] = true;
	for (int i = h[x]; i; i = tree[i].next)
	{
		if (!meet[tree[i].to]) {
			dfs(tree[i].to); 
			s[x] += s[tree[i].to];//統計兒子的答案
			if (tree[i].change == 0) s[x]++;//改變的統計
		}
	}
	meet[x] = false;
}

void Count(int num, int x, int dep)
{
	int pp = dep - num, ppx = num;//pp爲從根到當前點,需要改變多少條邊,ppx則爲反義
	int sum = s[1] - pp + ppx;//求出當前換點後的代價 
	if (sum < ans)
	{
		ans = sum;
		st[0] = 0;
		st[++st[0]] = x;//st爲題目要求的答案序列
	}//更新答案
	else if (sum == ans)
		st[++st[0]] = x;
	meet[x] = true;
	for (int i = h[x]; i; i = tree[i].next)
		if (!meet[tree[i].to])
			Count(num + tree[i].change, tree[i].to, dep + 1);
	meet[x] = false;
}

int main()
{
	scanf("%d", &n);
	for (int i = 1, x, y; i < n; ++i)
	{
		scanf("%d%d", &x, &y);
		tree[++t] = (Tree) {y, h[x], 1}; h[x] = t;
		tree[++t] = (Tree) {x, h[y], 0}; h[y] = t;
	}
	ans = 1e9;
	dfs(1);
	Count(0, 1, 0);
	printf("%d\n", ans);
	sort(st + 1, st + 1 + st[0]);
	for (int i = 1; i <= st[0]; ++i)
		printf("%d ", st[i]);
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章