题目链接
题意:给一个n节点的有向无环图,要找一个这样的点:该点到其它n-1要逆转的道路最少,(边<u,v>,如果v要到u去,则要逆转该边方向)如果有多个这样的点,则升序输出所有。
思路:将正边设为0,反边设为1,于是题目就变成了一个无向图,找到到其他各个点的路径最短,第一遍dfs时dp【i】代表i和它的子树的路径和,第二遍dfs时dp【i】代表以i为根时i到其他所有点的距离。最后取min就行了。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+1;
ll dp[maxn];
vector<pair<int,int>>g[maxn];
void dfs(int x,int fa)
{
for(auto to:g[x])
{
if(to.first==fa) continue;
dfs(to.first,x);
dp[x]+=dp[to.first]+to.second;
}
}
void dfs2(int x,int fa)
{
for(auto to:g[x])
{
if(to.first==fa) continue;
dp[to.first]+=dp[x]-dp[to.first]+((to.second==0)?1:-1);
dfs2(to.first,x);
}
}
int main()
{
int n,u,v;
scanf("%d",&n);
for(int i=1;i<n;++i)
{
scanf("%d %d",&u,&v);
g[u].push_back({v,0});
g[v].push_back({u,1});
}
dfs(1,-1);
dfs2(1,-1);
ll ans=1e18;
for(int i=1;i<=n;++i) ans=min(ans,dp[i]);
printf("%lld\n",ans);
for(int i=1;i<=n;++i) if(dp[i]==ans) printf("%d ",i);
}