CodeForces - 219D(树形dp)
多年不见树形dp。这个就是先以1为根,遍历出每个点到其下面点要改
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <queue> using namespace std; const int maxn=2000000+100; const int inf=0x3f3f3f3f; int d[maxn]; int step[maxn]; struct note { int to; int len; int next; }aa[maxn]; int hade[maxn]; int n,k; void addage(int fr,int to,int len) { aa[k].len=len; aa[k].to=to; aa[k].next=hade[fr]; hade[fr]=k++; } void dfs1(int u,int fa) { for(int i=hade[u];i!=-1;i=aa[i].next) { int v=aa[i].to; if(v==fa) continue; dfs1(v,u); d[u]+=d[v]+aa[i].len; } } void dfs2(int u,int fa) { for(int i=hade[u];i!=-1;i=aa[i].next) { int v=aa[i].to; if(v==fa) continue; d[v]+=(d[u]-d[v])+((aa[i].len)?-1:1);//以v为为根到其他点要反转的边数 dfs2(v,u); } } void init() { memset(hade,-1,sizeof(hade)); memset(step,0,sizeof(step)); memset(d,0,sizeof(d)); k=0; } int main() { while(~scanf("%d",&n)) { init(); int fr,to; for(int i=1;i<n;i++) { scanf("%d%d",&fr,&to); addage(fr,to,0); addage(to,fr,1); } dfs1(1,0); dfs2(1,0); int mini=inf,cnt=0; for(int i=1;i<=n;i++) { if(d[i]<mini) { memset(step,0,sizeof(step)); cnt=0; step[cnt++]=i; mini=d[i]; } else if(d[i]==mini) step[cnt++]=i; } printf("%d\n",mini); for(int i=0;i<cnt-1;i++) printf("%d ",step[i]); printf("%d\n",step[cnt-1]); } return 0; }
变的边数,然后再一遍dfs便利出每个点到其他点要改变的边数。