CF_D. Choosing Capital for Treeland_树形DP

来源:互联网 发布:flush软件 编辑:程序博客网 时间:2024/04/28 16:35
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <vector>#define INF 0x3f3f3f3f#define rep0(i, n) for (int i = 0; i < n; i++)#define rep1(i, n) for (int i = 1; i <= n; i++)#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)#define rep_1(i, n) for (int i = n; i > 0; i--)#define MAX(x, y) (((x) > (y)) ? (x) : (y))#define MIN(x, y) (((x) < (y)) ? (x) : (y))#define mem(x, y) memset(x, y, sizeof(x))/**题目大意树中的边为有向边 求其中的节点能到达树上的其他各节点而需要翻转的有向边的数量最少思路第一次dfs 由子节点更新父亲节点 在子树内需要反转的边数再由父节点跟新子节点的dp 如果父子之间的边指向父亲 则 dp[i] = dp[fa] - 1;else    dp[i] = dp[fa] + 1;*/using namespace std;const int MAXN = 2e5 + 10;struct Edge{    int from, to;    Edge(int f, int t): from(f), to(t) {}};vector<Edge> edges;int dp[MAXN];vector<int> g[MAXN];void addEdge(int from, int to){    edges.push_back(Edge(from, to));    int sz = edges.size();    g[from].push_back(sz - 1);    g[to].push_back(sz - 1);}void dfs(int u, int fa){    for (int i = 0; i < g[u].size(); i++)    {        Edge e = edges[g[u][i]];        if (e.from == fa || e.to == fa)            continue;        if (e.to == u)        {            dfs(e.from, u);            dp[u] += dp[e.from] + 1;        }        else        {            dfs(e.to, u);            dp[u] += dp[e.to];        }    }}int ans = INF;void dfs1(int u, int fa){    for (int i = 0; i < g[u].size(); i++)    {        Edge e = edges[g[u][i]];        if (e.from == fa || e.to == fa)            continue;        if (e.to == u)        {            dp[e.from] = dp[u] - 1;            ans = MIN(ans, dp[e.from]);            dfs1(e.from, u);        }        else        {            dp[e.to] = dp[u] + 1;            ans = MIN(ans, dp[e.to]);            dfs1(e.to, u);        }    }}int main(){    #ifndef ONLINE_JUDGE        freopen("in.txt", "r", stdin);    #endif // ONLINE_JUDGE;    int n, s, t;    scanf("%d", &n);    mem(dp, 0);    rep0(i, n - 1)    {        scanf("%d %d", &s, &t);        addEdge(s, t);    }    dfs(1, -1);    ans = MIN(ans, dp[1]);    dfs1(1, -1);       printf("%d\n", ans);    int i = 1;    while (dp[i] != ans)        i++;    printf("%d", i);    for (i++; i <= n; i++)        if (dp[i] == ans)            printf(" %d", i);    printf("\n");    return 0;}