https://cn.vjudge.net/contest/264707#problem/F
The country Treeland consists of n cities, some pairs of them are connected with unidirectional roads. Overall there are n - 1 roads in the country. We know that if we don’t take the direction of the roads into consideration, we can get from any city to any other one.
The council of the elders has recently decided to choose the capital of Treeland. Of course it should be a city of this country. The council is supposed to meet in the capital and regularly move from the capital to other cities (at this stage nobody is thinking about getting back to the capital from these cities). For that reason if city a is chosen a capital, then all roads must be oriented so that if we move along them, we can get from city a to any other city. For that some roads may have to be inversed.
Help the elders to choose the capital so that they have to inverse the minimum number of roads in the country.
题意为一个有向图国家,n个城市有n-1条边,需要我们选出一个城市,从这个国家出发到其他国家需要翻转路径方向的最小值。
我的思路是还是建图成无向图,标记初始方向和翻转方向,dfs过程中判断经过了多少条翻转边,发现状态无法保存
正解也是建图成无向图,然后把初始方向权值设为1,翻转反向权值设为0,求出从每个点出发的最大权值即可
分别正序和逆序进行dfs,表示从子树累积的权值,和从父亲累计的权值
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
const int inf = 0x3f3f3f3f;
vector< pair<int, int> > e[maxn];
int dp[maxn][2]; //1->son, 2->fa
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int n;
while(cin >> n) {
for(int i = 1; i <= n; i++) {
e[i].clear();
dp[i][0] = dp[i][1] = 0;
}
for(int i = 1; i < n; i++) {
int u, v;
cin >> u >> v;
e[u].emplace_back(v, 1);
e[v].emplace_back(u, 0);
}
function<void(int, int)> dfs_positive = [&](int u, int pre) {
for(auto& x : e[u]) {
int v = x.first, w = x.second;
if(v == pre) continue;
dfs_positive(v, u);
dp[u][0] += dp[v][0] + w;
}
};
dfs_positive(1, 0);
function<void(int, int)> dfs_reverse = [&](int u, int pre) {
for(auto& x : e[u]) {
int v = x.first, w = x.second;
if(v == pre) continue;
dp[v][1] = dp[u][1] + (w ^ 1) + dp[u][0] - dp[v][0] - w;
//还需要加上除当前pre这个父亲其他子树的贡献
dfs_reverse(v, u);
}
};
dfs_reverse(1, 0);
vector<int> ans(n + 1);
int sz = inf;
for(int i = 1; i <= n; i++) {
if(n - 1 - dp[i][1] - dp[i][0] < sz) {
sz = n - 1 - dp[i][1] - dp[i][0];
ans.clear();
ans.emplace_back(i);
}
else if(n - 1- dp[i][1] - dp[i][0] == sz)
ans.emplace_back(i);
}
cout << sz << '\n';
for(int i = 0; i < ans.size(); i++) {
if(i == 0) cout << ans[i];
else cout << ' ' << ans[i];
}
cout << endl;
}
}