题目:给出一棵树,但是它的边是有向边,选择一个城市,问最少调整多少条边的方向能使一个选中城市可以到达所有的点,输出最小的调整的边数,和对应的点。(题意是copy别人的来的,自己说的太绕了)
树形dp,dp[u]表示从u走到其所有的子节点需要的调整数,dpf[u]表示往父节点走需要的调整数,dp[u]+dpf[u]便是所有的调整数。dp[u]比较好求,dpf[u]+=dpf[father];
当father—>u时:dpf[u]+=dp[father]-dp[u]+1;
当father<—u时:dpf[u]+=dp[father]-(dp[u]+1);
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
struct node{
int x,val;
node(int _x,int _val)
{
x=_x;
val=_val;
}
};
vector<node>a[maxn];
int dp[maxn],n;
void dfs(int u,int fa)
{
for(int i=0;i<a[u].size();i++)
{
int v=a[u][i].x,flag=a[u][i].val;
if(v==fa) continue;
dfs(v,u);
dp[u]+=dp[v];
if(flag==0)
dp[u]++;
}
}
int dpf[maxn];
void DFS(int u,int fa)
{
for(int i=0;i<a[u].size();i++)
{
int v=a[u][i].x,flag=a[u][i].val;
if(v==fa) continue;
if(flag)
dpf[v]+=dp[u]-dp[v]+1;
else dpf[v]+=dp[u]-dp[v]-1;
dpf[v]+=dpf[u];
DFS(v,u);
}
}
int main()
{
///cout << "Hello world!" << endl;
///freopen("in.txt","r",stdin);
while(~scanf("%d",&n))
{
for(int i=1;i<=n;i++)
a[i].clear();
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
a[x].push_back(node(y,1));
a[y].push_back(node(x,0));
}
memset(dp,0,sizeof dp);
memset(dpf,0,sizeof dpf);
dfs(1,0);
DFS(1,0);
int mi=maxn,num=0;
for(int i=1;i<=n;i++)
{
int tmp=dp[i]+dpf[i];
if(tmp<mi)
{
mi=tmp;
num=1;
}
else
if(mi==tmp)
num++;
}
printf("%d\n",mi);
for(int i=1;i<=n;i++)
if(dp[i]+dpf[i]==mi)
{
num--;
if(num) printf("%d ",i);
else printf("%d\n",i);
}
}
return 0;
}