题意:有向树,要求找最小的需要修改边的方向的数目,使得该点能到达树上每一个点,并求出所有最小数目的点
解法:树形dp,先从1开始dfs一遍(dp【u】是以u为根 的子树需要修改的边数)转移方程如果是u->x,dp【x】+=dp【u】+1,否则dp【x】+=dp【u】,再把dp【i】的意义改成以u为根的需要修改的边数,重新dfs一遍,转移方程if:u->x,dp【x】=dp【u】+1,else:dp【x】=dp【u】-1
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 1000000007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; using namespace __gnu_cxx; const double g=10.0,eps=1e-7; const int N=200000+10,maxn=60000+10,inf=0x3f3f3f3f; vector<int>v[N]; map<int,int>m[N]; int dp[N]; void dfs(int u,int f) { for(int i=0;i<v[u].size();i++) { int x=v[u][i]; if(x==f)continue; dfs(x,u); if(m[u][x])dp[u]+=dp[x]; else dp[u]+=dp[x]+1; } } void dfs1(int u,int f) { for(int i=0;i<v[u].size();i++) { int x=v[u][i]; if(x==f)continue; if(m[u][x])dp[x]=dp[u]+1; else dp[x]=dp[u]-1; dfs1(x,u); } } int main() { ios::sync_with_stdio(false); cin.tie(0); int n; cin>>n; for(int i=1;i<n;i++) { int a,b; cin>>a>>b; v[a].pb(b); v[b].pb(a); m[a][b]=1; } dfs(1,-1); dfs1(1,-1); int minn=300000; for(int i=1;i<=n;i++)minn=min(minn,dp[i]); cout<<minn<<endl; for(int i=1;i<=n;i++) if(dp[i]==minn) cout<<i<<" "; return 0; } /************ ************/