• CF 219D 树形DP


    CF 219D

    【题目链接】CF 219D

    【题目类型】树形DP

    &题意:

    给一个n节点的有向无环图,要找一个这样的点:该点到其它n-1要逆转的道路最少,(边<u,v>,如果v要到u去,则要逆转该边方向)如果有多个这样的点,则升序输出所有。

    &题解:

    参考自:http://blog.csdn.net/angon823/article/details/52316220
    需要求每个点到其他n-1个点是否要逆转路径,那么就可以把正的路cost=1,逆转的cost=0,这只要求这个点到其他点的cost,之后用所有的也就是n-1条边减去这个就好了。求一个点到其他点的cost,可以用树形DP来求,u点的cost=u子树的cost+其他的cost

    &代码:

    #include <map>
    #include <cmath>
    #include <cstdio>
    #include <vector>
    #include <iostream>
    #include <set>
    #include <queue>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    #define cle(a,v) memset(a,(v),sizeof(a))
    #define ll long long
    const int maxn = 2e5 + 7;
    
    struct Edge {
    	int v, w, next;
    } edges[maxn * 2];
    int head[maxn], tot;
    void addedge(int u, int v, int w) {
    	edges[tot] = Edge{v, w, head[u]};
    	head[u] = tot++;
    }
    int n, dpson[maxn], dpfa[maxn];
    void dfs1(int u, int fa) {
    	for (int i = head[u]; ~i; i = edges[i].next) {
    		int v = edges[i].v;
    		int w = edges[i].w;
    		if (v != fa) {
    			dfs1(v, u);
    			dpson[u] += dpson[v] + w;
    		}
    	}
    }
    void dfs2(int u, int fa) {
    	for (int i = head[u]; i != -1; i = edges[i].next) {
    		int v = edges[i].v;
    		int w = edges[i].w;
    		if (v == fa) continue;
    		dpfa[v] = dpfa[u] + (w ? 0 : 1) + dpson[u] - dpson[v] - w;
    		dfs2(v, u);
    	}
    }
    int main() {
    	freopen("1.in", "r", stdin);
    	cle(head, -1); tot = 0;
    	cle(dpson, 0);
    	cle(dpfa, 0);
    	scanf("%d", &n);
    	for (int i = 1; i < n; i++) {
    		int u, v;
    		scanf("%d%d", &u, &v);
    		addedge(u, v, 1);
    		addedge(v, u, 0);
    	}
    	dfs1(1, -1);
    	dfs2(1, -1);
    	vector<pair<int, int>> vp;
    	for (int i = 1; i <= n; i++) {
    		vp.push_back(make_pair(dpson[i] + dpfa[i], i));
    	}
    	sort(vp.begin(), vp.end());
    	int t1 = vp[n - 1].first;
    	int i;
    	for (i = n - 2; i >= 0; i--) {
    		if (vp[i].first != t1) {
    			break;
    		}
    	}
    	printf("%d
    ", n - 1 - vp[n - 1].first);
    	for (int j = i + 1; j < n; j++) {
    		printf("%d%c", vp[j].second, j == n - 1 ? '
    ' : ' ');
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    Apache、NGINX支持中文URL
    JS中关于clientWidth offsetWidth scrollWidth 等的含义
    设置apache登陆密码验证
    通过java代码访问远程主机
    win7
    Netty从没听过到入门 -- 服务器端详解
    分块分段
    数论-佩尔方程
    数论-毕达哥拉斯三元组
    HDU 5613-Baby Ming and Binary image
  • 原文地址:https://www.cnblogs.com/s1124yy/p/7272863.html
Copyright © 2020-2023  润新知