【DFS】Candy选首都(treeland)

DescriptionDescriptionDescription

Treeland是一个有n个城市组成的国家,其中一些城市之间有单向边连通。在这个国家中一共有n-1条路。我们知道,如果我们不考虑路的方向,那么我可以从任意城市到达任意城市。
最近,Treeland的总理Candy为了发展经济,想要从这n个城市中选择一个作为Treeland的首都,首都必须要能到达其他任意城市,这使得有些道路必须反向,付出的代价即需要反向的道路条数。
Candy想要选择一个城市作为首都,使得付出的代价最小。可能有多个城市满足条件,按编号从小到大输出。

InputInputInput

第一行,一个整数n,表示城市个数
接下来n-1行,每行两个整数x、y,表示城市x到城市y之间有一条单向路径

OutputOutputOutput

第一行,一个整数k,花费的最小代价。
第二行若干个整数,中间用空格隔开,表示满足条件的城市编号。行末没有多余的空格。

SampleInputSample InputSampleInput#111
3
2 1
2 3
SampleInputSample InputSampleInput#222
4
1 4
2 4
3 4
SampleOutputSample OutputSampleOutput#111
0
2
SampleOutputSample OutputSampleOutput#222
2
1 2 3

思路

首先不考虑他的方向
它就变成了一棵树
把某个点当成根节点(首都)
然后把每一个点到达根节点(首都)的代价存起来
再然后深搜
遍历每一个点时
可以发现除了他经过的边
到达其他点的代价都与到达根节点(首都)的代价相同
然后换根,计算答案

#include<algorithm>
#include<iostream>
#include<cstdio>
using namespace std;
int h[400250], A[400250], T[400250], cr[400250];
int Ans, n, x, y, t;
struct whw
{
	int w,h,k;
}wh[400250];
void Dfs(int k)
{
	T[k] = 1;
	for(int i = h[k]; i; i = wh[i].h)
		if(!T[wh[i].w])
		{
			Dfs(wh[i].w);
			A[k] += A[wh[i].w];
			if(!wh[i].k) A[k]++;
		}
	T[k] = 0;
}
void init(int num, int k, int sum)
{
	int tot = A[1] - sum + num * 2;
	if (tot < Ans)
	{
		Ans = tot;
		cr[0] = 0;
		cr[++cr[0]] = k;
	}
	else if(tot == Ans) cr[++cr[0]] = k;
	T[k] = 1;
	for(int i = h[k]; i; i = wh[i].h)
		if(!T[wh[i].w])
			init(num + wh[i].k, wh[i].w, sum+1);
	T[k] = 0;
}
int main()
{
	scanf("%d", &n);
	for(int i = 1; i < n; ++i)
	{
		scanf("%d%d", &x, &y);
		wh[++t] = (whw){y, h[x], 1}, h[x] = t;
		wh[++t] = (whw){x, h[y], 0}, h[y] = t;
	}
	Dfs(1);
	Ans = 1e9;
	init(0, 1, 0);
	printf("%d\n", Ans);
	sort(cr + 1, cr + 1 +cr[0]);
	for(int i = 1; i <= cr[0]; ++i)
		printf("%d ", cr[i]);
	return 0;
	
}
上一篇:linux文本三剑客之sed命令详解


下一篇:UVM中sequence的两种启动方式