CodeForces

来源:互联网 发布:clean my mac有必要吗 编辑:程序博客网 时间:2024/06/03 22:07

类似于树上每个点的最远距离那种思路,两遍dfs,一遍求儿子的反转个数,另一个求父亲的反转个数(中间会用到兄弟),最后结果为两部分相加

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;const int INF = 0x3f3f3f3f;const int maxn = 2 * 1e5 + 10;int n, tot, head[maxn];struct Edge {    int to, flag, next;}edge[maxn<<1];void init() {    tot = 0;    memset(head, -1, sizeof(head));}void addedge(int u, int v, int flag) {    ++tot;    edge[tot].to = v, edge[tot].flag = flag, edge[tot].next = head[u];    head[u] = tot;}int dp[maxn][2];void dfs1(int u, int p) {    for (int i = head[u]; i != -1; i = edge[i].next) {        int v = edge[i].to, flag = edge[i].flag;        if (v == p) continue;        dfs1(v, u);        dp[u][0] += dp[v][0] + (flag ? 0 : 1);    }}void dfs2(int u, int p) {    for (int i = head[u]; i != -1; i = edge[i].next) {        int v = edge[i].to, flag = edge[i].flag;        if (v == p) continue;        dp[v][1] = dp[u][1] + (flag ? dp[u][0] - dp[v][0] + 1 : dp[u][0] - dp[v][0] - 1);        dfs2(v, u);    }}int main() {    scanf("%d", &n);    init();    int u, v;    for (int i = 1; i <= n - 1; i++) {        scanf("%d %d", &u, &v);        addedge(u, v, 1);        addedge(v, u, 0);    }    memset(dp, 0, sizeof(dp));    dfs1(1, -1);    dfs2(1, -1);//    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;    int ans = INF, flag = 0;    for (int i = 1; i <= n; i++) ans = min(ans, dp[i][0] + dp[i][1]);    printf("%d\n", ans);    for (int i = 1; i <= n; i++) {        if (dp[i][0] + dp[i][1] == ans) {            if (flag++) printf(" ");            printf("%d", i);        }    }    return 0;}