Solution - P7687 [CEOI 2005] Critical Network Lines

十年 OI 一场空,不该用的就别用。

——记我一开 set 就去世的代码

思路

其实很简单。一个边是重要的,当且仅当其一头没有任何可用的服务。

于是 tarjan 缩点,DFS。又观察到如果父节点方向没有可用的服务那么子节点就点满了该种服务,于是扫一遍,完了。

代码

#include <bits/stdc++.h>
#define rint register int
#define rllong register long long
#define llong long long
#define N 100005
#define M 2000006
using namespace std;

int to[M], nxt[M], head[N], gsiz = 1;
#define mkarc(u,v) (++gsiz,to[gsiz]=v,nxt[gsiz]=head[u],head[u]=gsiz)
int to2[M], nxt2[M], rs2[M], rt2[M], head2[N], gsiz2 = 1;
#define mkarc2(u,v) (++gsiz2,to2[gsiz2]=v,nxt2[gsiz2]=head2[u],head2[u]=gsiz2)
int low[N], dfn[N], dfcnt;
int belong[N], n2, sta[N], top, vis[M];
int isa[N], isb[N], cnta[N], cntb[N];
int n, m, c1, c2;

inline void tarjan(rint u){
	dfn[u] = low[u] = ++dfcnt;
	sta[++top] = u;
	for(rint i = head[u]; i; i = nxt[i]){
		if(vis[i^1]) continue;
		vis[i] = true;
		rint v = to[i];
		if(!dfn[v]){
			tarjan(v);
			low[u] = min(low[u], low[v]);
			if(low[v] > dfn[u]){
				++n2;
				while(sta[top+1] != v){
					belong[sta[top]] = n2;
					cnta[n2] += isa[sta[top]];
					cntb[n2] += isb[sta[top]];
					--top;
				}
			}
		}
		else low[u] = min(low[u], dfn[v]);
	}
	if(u == 1){
		++n2;
		while(sta[top+1] != u){
			belong[sta[top]] = n2;
			cnta[n2] += isa[sta[top]];
			cntb[n2] += isb[sta[top]];
			--top;
		}
	}
	return;
}

typedef pair<int, int> Node;
int ansu[M], ansv[M], cnt;

inline void dfs(rint u, rint fa, rint& cnt1, rint& cnt2){
	cnt1 += cnta[u], cnt2 += cntb[u];
	for(rint i = head2[u]; i; i = nxt2[i]){
		rint v = to2[i], ru = rs2[i], rv = rt2[i];
		if(v == fa) continue;
		rint cntva = 0, cntvb = 0;
		dfs(v, u, cntva, cntvb);
		if(cntva == 0 || cntvb == 0 || cntva == c1 || cntvb == c2)
			++cnt, ansu[cnt] = ru, ansv[cnt] = rv;
		cnt1 += cntva, cnt2 += cntvb;
	}
	return;
}

int main(){
	scanf("%d %d %d %d", &n, &m, &c1, &c2);
	for(rint i = 1, x; i <= c1; ++i)
		scanf("%d", &x), isa[x] = true;
	for(rint i = 1, x; i <= c2; ++i)
		scanf("%d", &x), isb[x] = true;
	for(rint i = 1; i <= m; ++i){
		rint u, v;
		scanf("%d %d", &u, &v);
		mkarc(u, v), mkarc(v, u);
	}
	tarjan(1);
	for(rint u = 1; u <= n; ++u){
		for(rint i = head[u]; i; i = nxt[i]){
			rint v = to[i];
			if(belong[u] != belong[v]){
				mkarc2(belong[u], belong[v]), rs2[gsiz2] = u, rt2[gsiz2] = v;
			}
		}
	}
	rint cnt1 = 0, cnt2 = 0;
	dfs(n2, 0, cnt1, cnt2);
	printf("%d\n", cnt);
	for(rint i = 1; i <= cnt; ++i)
		printf("%d %d\n", ansu[i], ansv[i]);
	return 0;
} 

posted @ 2025-05-13 22:16  Hootime  阅读(3)  评论(0)    收藏  举报