• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
ACM s1124yy
守りたいものが 強くさせること
博客园    首页    新随笔    联系   管理     

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", n - 1 - vp[n - 1].first);
	for (int j = i + 1; j < n; j++) {
		printf("%d%c", vp[j].second, j == n - 1 ? '\n' : ' ');
	}
	return 0;
}

posted @ 2017-08-02 11:13  s1124yy  阅读(319)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3