这种题以后一定要拿下。。
http://www.cnblogs.com/–ZHIYUAN/p/5786233.html
题意:
给出N个点,其中有N-1条有向边,边的方向可以改变,问最少改变多少条边可以从某一个点到达任意一个点,同时求出这些点。
struct Edge{
int u,v,nxt,val;
}edge[mxn<<1];
int dp[mxn],head[mxn],tot;
void add(int u,int v,int val){
edge[tot].v=v;
edge[tot].u=u;
edge[tot].val=val;
edge[tot].nxt=head[u];
head[u]=tot++;
}
void dfs(int u,int fa){
int ret=0;
for(int i=head[u];~i;i=edge[i].nxt){
int v=edge[i].v;
if(v==fa)continue;
dfs(v,u);
dp[u]+=dp[v]+edge[i].val;
}
}
int res[mxn];
void dfs1(int u,int fa){
for(int i=head[u];~i;i=edge[i].nxt){
int v=edge[i].v;
if(v==fa)continue;
dp[v]+=(dp[u]-dp[v])+((edge[i].val)?-1:1);
dfs1(v,u);
}
}
int main(){
int n; sf("%d",&n);mem(head,-1);tot=0;
rep(i,1,n-1){int u,v; sf("%d%d",&u,&v);add(u,v,0);add(v,u,1); }
mem(dp,0);
dfs(1,1);
dfs1(1,1);
int ans=1000000;
int cnt=0;
for(int i=1;i<=n;++i){
if(dp[i]<ans){
mem(res,0);
cnt=0;
res[++cnt]=i;
ans=dp[i];
}
else if(dp[i]==ans){
res[++cnt]=i;
}
}
pf("%d\n",ans);
for(int i=1;i<=cnt;++i){
pf("%d%c",res[i],i==cnt?'\n':' ');
}
}