题目链接:CF219D Choosing Capital for Treeland
题意:Treeland国有n个城市,这n个城市连成了一颗树,有n-1条道路连接了所有城市。每条道路只能单向通行。现在政府需要决定选择哪个城市为首都。假如城市i成为了首都,那么为了使首都能到达任意一个城市,不得不将一些道路翻转方向,记翻转道路的条数为k。你的任务是找到所有满足k最小的首都。
随便找一个点 r t rt rt 跑一遍dfs,求出这个 d p [ r t ] dp[rt] dp[rt] 的值
然后 d p [ u ] → d p [ v ] dp[u] to dp[v] dp[u]→dp[v] 的转移显然与 ( u , v ) (u,v) (u,v) 有关
判断一下然后转移一下就没了
题外话:真的离了谱了,我换电脑之前写的这篇文章没发博客上,然后今天20220606花了2小时用爬虫和自己写的比对程序搞了半天才发现(恼
代码:
#includeusing namespace std; #define int long long #define INF 0x3f3f3f3f3f3f3f3f #define N (int)(2e5+15) struct Edge { int u,v,next; }e[N<<1]; int n,dp[N]; int pos=1,head[N],r[N<<1]; void addEdge(int u,int v) { e[++pos]={u,v,head[u]}; head[u]=pos; } int dfs1(int u,int f) { int res=0; for(int i=head[u]; i; i=e[i].next) { int v=e[i].v; if(v==f)continue; if(!r[i])++res; res+=dfs1(v,u); } return res; } void dfs2(int u,int f) { dp[u]+=dp[f]; for(int i=head[u]; i; i=e[i].next) { int v=e[i].v; if(v==f)continue; if(r[i])++dp[v]; else --dp[v]; dfs2(v,u); } } signed main() { ios::sync_with_stdio(0); cin.tie(0);cout.tie(0); // freopen("check.in","r",stdin); // freopen("check.out","w",stdout); cin >> n; for(int i=1,u,v; i cin >> u >> v; addEdge(u,v);r[pos]=1; addEdge(v,u); } dp[1]=dfs1(1,0);int mn=INF; dfs2(1,0); for(int i=1; i<=n; i++) mn=min(mn,dp[i]); cout << mn << endl; for(int i=1; i<=n; i++) if(dp[i]==mn)cout << i << " "; return 0; }
转载请说明出处



