题目大意:
给一个n节点的有向无环图,要找一个这样的点,该点到其它n-1要逆转的道路最少;
题解思路:
建边时正边赋值0,反边赋值1;及遍历全图后总权值最小。
跑树形dp; 可以从一个结点可以从fa son得到值;
2遍dfs;
#include<bits/stdc++.h> using namespace std; #define ll long long #define mem(a,b) memset(a,b,sizeof(a)) #define inf 0x3f3f3f3f const int maxn=4e5+10; struct edge{ int u,v,w,next; }e[maxn]; int g[maxn],tot=0; int dp[maxn][2],vis[maxn]; void creat_edge(int u,int v,int w) { e[++tot]=(edge){u,v,w,g[u]}; g[u]=tot; } void dfs(int u) { vis[u]=1; for(int i=g[u];i>0;i=e[i].next) { int v=e[i].v,w=e[i].w; if(vis[v]) continue; dfs(v); dp[u][0]+=dp[v][0]+w; } } void dfs1(int u) { vis[u]=1; for(int i=g[u];i>0;i=e[i].next) { int v=e[i].v,w=e[i].w; if(vis[v]) continue; dp[v][1]+=dp[u][1]+dp[u][0]-dp[v][0]-w+(w?0:1); dfs1(v); } dp[u][1]+=dp[u][0]; } int main() { int n; scanf("%d",&n); for(int i=1;i<n;i++) { int u,v; scanf("%d%d",&u,&v); creat_edge(u,v,0); creat_edge(v,u,1); } mem(vis,0); dfs(1); mem(vis,0); dfs1(1); int ans=inf; // for(int i=1;i<=n;i++) // { // cout<<dp[i][0]<<" "; // }cout<<endl; // // for(int i=1;i<=n;i++) // { // cout<<dp[i][1]<<" "; // }cout<<endl; for(int i=1;i<=n;i++) { if(dp[i][1]<ans) ans=dp[i][1]; } cout<<ans<<endl; int f=1; for(int i=1;i<=n;i++) { if(dp[i][1]==ans) { if(!f) cout<<" "; cout<<i; f=0; } } return 0; }