Codeforces 219D Choosing Capital for Treeland DP(Tree)

来源:互联网 发布:我的世界,java.net 编辑:程序博客网 时间:2024/06/05 16:40
题意:n个点n-1条有向边,f[x]为把x点设为首都的代价即:要反转多少条边 使得x能达到任意一个城市.
n<=2e5,求出最小代价及相应的点集.

标记边方向后 建立有根无向的树,dfs算出f[1],

因为fa,u的f值只差(fa,u)这条边的方向,所以fa和son的f值相差正负1,自顶向下DP一次即可

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N=4e5+20;map<int,int> mp[N];vector<int> e[N];int f[N];void dfs(int u,int fa){f[u]=0;for(int i=0;i<e[u].size();i++){int v=e[u][i];if(v==fa)continue;dfs(v,u);f[u]+=f[v];if(mp[u][v]==0)f[u]++;}}void dfs2(int u,int fa){for(int i=0;i<e[u].size();i++){int v=e[u][i];if(v==fa)continue;if(mp[u][v])f[v]=f[u]+1;elsef[v]=f[u]-1;dfs2(v,u);}}int main(){int n;while(cin>>n){int u,v;for(int i=1;i<=n-1;i++){scanf("%d%d",&u,&v);mp[u][v]=1;e[u].push_back(v);e[v].push_back(u);}dfs(1,0);dfs2(1,0);int mn=2e5;for(int i=1;i<=n;i++)mn=min(mn,f[i]),e[i].clear(),mp[i].clear();cout<<mn<<endl;for(int i=1;i<=n;i++)if(f[i]==mn)printf("%d ",i);printf("\n");}return 0;}


阅读全文
0 0