树形DP Choosing Capital for Treeland
给你一棵有向树,需要选定一个点为capital,满足翻转边数最小
思路:先求出1为capital 的答案,然后向下更新孩子节点
dp[i]=dp[i-1]+judge(i);
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #include<stack> #include<vector> #include<set> #include<map> #define L(x) (x<<1) #define R(x) (x<<1|1) #define MID(x,y) ((x+y)>>1) #define bug printf("hihi\n") #define eps 1e-8 typedef __int64 ll; using namespace std; #define INF 0x3f3f3f3f #define N 200005 int dp[N]; int n; struct stud{ int to,ne,len; }e[N*2]; int head[N]; int num; inline void add(int u,int v,int len) { e[num].to=v; e[num].len=len; e[num].ne=head[u]; head[u]=num++; } void dfs(int u,int pre) { dp[u]=0; for(int i=head[u];i!=-1;i=e[i].ne) { int to=e[i].to; if(to==pre) continue; dfs(to,u); dp[u]+=dp[to]+e[i].len; } } void dfsup(int u,int pre) { for(int i=head[u];i!=-1;i=e[i].ne) { int to=e[i].to; if(to==pre) continue; dp[to]=dp[u]; if(e[i].len) dp[to]--; else dp[to]++; dfsup(to,u); } } int main() { int i,j; while(~scanf("%d",&n)) { memset(head,-1,sizeof(head)); num=0; int u,v; i=n-1; while(i--) { scanf("%d%d",&u,&v); add(u,v,0); add(v,u,1); } dfs(1,-1); dfsup(1,-1); int ans=INF; for(i=1;i<=n;i++) ans=min(ans,dp[i]); printf("%d\n",ans); vector<int>temp; temp.clear(); for(i=1;i<=n;i++) if(dp[i]==ans) temp.push_back(i); for(i=0;i<temp.size();i++) { if(i) printf(" "); printf("%d",temp[i]); } printf("\n"); } return 0; }