CF521E Cycling City

https://www.luogu.com.cn/problem/CF521E
题目大意
给你一个无向图,问图中是否存在两个点,连点之间至少有3条完全不相交的路径
输出三条路径
题解
一开始不太会做啊
还是要静下心来一步步画图推
CF521E Cycling City
首先肯定是先拉出一棵树,然后发现如果有一条边被覆盖了超过三次(LCA->D),那么就可以抽出三条路径

  • LCA -> A -> C-> D
  • LCA -> D
  • LCA -> B -> D

具体实现可以暴力覆盖
因为每条边最多覆盖3次,所以是线性的
康康代码吧
code:

#include<bits/stdc++.h>
#define N 200050
using namespace std;
struct edge {
	int v, nxt;
} e[N << 1];
int p[N], eid;
void init() {
	memset(p, -1, sizeof p);
	eid = 0;
}
void insert(int u, int v) {
	e[eid].v = v;
	e[eid].nxt = p[u];
	p[u] = eid ++;
}
int dep[N], fa[N], ans[N], gs, hx[N], hy[N], vis[N], in[N], n, m;
int LCA(int x, int y) {
	while(dep[x] > dep[y]) x = fa[x];
	while(dep[x] < dep[y]) y = fa[y];
	while(x != y) x = fa[x], y = fa[y];
	return x;
}
void gett(int x, int y) {
	while(x != y) {
		ans[++ gs] = x;
		x = fa[x];
	}
	ans[++ gs] = x;
}
void print() { printf("%d ", gs);
	for(int i = 1; i <= gs; i ++) printf("%d ", ans[i]); printf("\n");
	gs = 0;
}
void get(int a, int b, int c, int d) {
	if(dep[b] > dep[d]) {
		swap(b, d), swap(a, c);
	}
	int lca = LCA(a, c);
	puts("YES");
	
	gett(lca, d);
	reverse(ans + 1, ans + 1 + gs);
	print();
	
	gett(d, b), gett(a, lca);
	print();
	
	ans[++ gs] = d; gett(c, lca);
	print();
	
	exit(0);	
}
void dfs(int u) {
	dep[u] = dep[fa[u]] + 1;
	vis[u] = in[u] = 1;
	for(int i = p[u]; i + 1; i = e[i].nxt) {
		int v = e[i].v;
		if(v == fa[u]) continue;
		if(!vis[v]) {
			fa[v] = u;
			dfs(v);
		} else if(in[v]) {
			for(int x = u; x != v; x = fa[x]) {
				if(hx[x] && hy[x]) get(hx[x], hy[x], u, v);
				else {
					hx[x] = u; hy[x] = v;
				}
			}
		}
	}
	in[u] = 0;
}
int main() {
	init();
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= m; i ++) {
		int u, v;
		scanf("%d%d", &u, &v);
		insert(u, v), insert(v, u);
	}
	for(int i = 1; i <= n; i ++) if(!vis[i]) dfs(i);
	puts("NO");
	return 0;
}

多画图
多思考

上一篇:模拟退火算法(SA)和迭代局部搜索(ILS)求解TSP的Java代码分享


下一篇:c1任务认证04