CodeForces 589H Tourist Guide(树形DP)

来源:互联网 发布:淘宝店纳亮索尼怎么样 编辑:程序博客网 时间:2024/06/05 08:41

题目链接:http://codeforces.com/problemset/problem/589/H


题意:给出一张无向图,图上有些点是被标记的,现在要找出尽量多的路径满足:

1.路径的起点和终点都是被标记过的点

2.每个被标记的点最多只能作为某一路径的端点

3.任意两条路径不能有公共边


思路:考虑可以把环切开当成树来做,那么对于子树,如果该子树内有偶数个标记点,那么就可以两两匹配成路径,如果是奇数个点,那就将多出的那个点与其他子树多出来的点相匹配


#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#include <vector>#include <utility>#include <cmath>#include <queue>#include <set>#include <map>#include <climits>#include <functional>#include <deque>#include <ctime>#include <string>#define lson l, mid, rt << 1#define rson mid + 1, r, rt << 1 | 1#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;typedef long long ll;const int maxn = 100010;struct UF{int fa[maxn];void init(int n){for (int i = 0; i <= n; i++)fa[i] = i;}int Find(int x){if (fa[x] == x) return x;return fa[x] = Find(fa[x]);}} uf;int deep[maxn], fa[maxn], road[maxn];int head[maxn], tot;bool flag[maxn], vis[maxn];int ans;struct Edge{int to, next;} e[maxn << 1];void init(){tot = 0;memset(head, -1, sizeof(head));}void addedge(int u, int v){e[tot].to = v;e[tot].next = head[u];head[u] = tot++;}int dfs(int u, int pre){vis[u] = true;deep[u] = deep[pre] + 1;fa[u] = pre;int now = -1, nxt = -1;int sz = 0;for (int i = head[u]; ~i; i = e[i].next){int v = e[i].to;if (v == pre || vis[v]) continue;//  printf("***********%d %d %d\n", u, v, pre);sz++;nxt = dfs(v, u);if (nxt == -1) continue;if (now == -1) now = nxt;else{road[now] = nxt;road[nxt] = now;//printf("%d %d\n", now, nxt);now = -1;ans++;}}if (flag[u]){if (now == -1) now = u;else{road[now] = u;road[u] = now;//printf("%d %d\n", now, nxt);now = -1;ans++;}}return now;}void Init(int n){ans = 0;init();uf.init(n);memset(flag, false, sizeof(flag));memset(vis, false, sizeof(vis));memset(road, -1, sizeof(road));}int main(){int n, m, k;while (~scanf("%d%d%d", &n, &m, &k)){Init(n);for (int i = 0; i < m; i++){int u, v;scanf("%d%d", &u, &v);int fu = uf.Find(u);int fv = uf.Find(v);if (fu != fv){uf.fa[fu] = fv;addedge(u, v);addedge(v, u);}}for (int i = 1; i <= k; i++){int x;scanf("%d", &x);flag[x] = true;}for (int i = 1; i <= n; i++) if (!vis[i]) dfs(i, -1);cout << ans << endl;for (int i = 1; i <= n; i++){if (road[i] > i){int x = i, y = road[i];//printf("********** %d %d\n", x, y);if (deep[x] > deep[y]) swap(x, y);vector <int> vx, vy;while (deep[y] > deep[x]){vy.push_back(y);y = fa[y];}while (x != y){vx.push_back(x), vy.push_back(y);x = fa[x], y = fa[y];}int sx = vx.size(), sy = vy.size();printf("%d", sx + sy);for (int j = 0; j < sx; j++)printf(" %d", vx[j]);printf(" %d", y);for (int j = sy - 1; j >= 0; j--)printf(" %d", vy[j]);printf("\n");}}}return 0;}


0 0
原创粉丝点击