这题就是给你一棵有向树,需要选定一个点为capital,满足翻转边数最小。
题解:
深搜。假设父亲知道了翻转的条数,那么儿子的翻转条数也就知道了。(看父亲跟儿子之间的边的方向)。
抄完了代码还是觉得很神,恍如隔世。
#include <cstdio>
#include <iostream>
using namespace std;
int tot = 0,out[222222],in[222222],head[222222],n;
#include <vector>
vector <int> io[222222],edge[222222],cap;
void dfs(int x, int p, int i, int o){
in[x] = i;
out[x] = o;
for(int j = 0; j < edge[x].size(); j ++){
int y = edge[x][j];
if(y == p) continue ;
if(io[x][j] == -1){
tot ++;
dfs(y,x,i,o + 1);
}else
dfs(y,x,i + 1,o);
}
}
int main(){
scanf("%d",&n);
int a,b;
for(int i = 0; i < n - 1; i ++){
scanf("%d%d",&a,&b);
edge[a].push_back(b);
edge[b].push_back(a);
io[a].push_back(1);//1 表示出去
io[b].push_back(-1);//-1 表示进来
}
dfs(1,0,0,0); int ans = n;
for(int i = 1; i <= n; i ++){
int tmp = tot - out[i] + in[i];
if(tmp < ans){
ans = tmp;
cap.clear();
cap.push_back(i);
}else if(ans == tmp)
cap.push_back(i);
}
printf("%d\n",ans);
for(int i = 0; i < cap.size(); ++ i)
printf("%d ",cap[i]);
printf("\n");
return 0;
}