【bzoj2140】稳定婚姻 强连通分量

       这道题目建图还是很奇妙的。

       把一对夫妻抽象为一个点i。那么如果夫妻对i的男方和夫妻对j的女方有关♂(jian)♀系♂(qing),那么就连一条边i->j,那么如果存在一个环就说明不(hui)安(chu)全(gui)。

       Tarjan强连通分量跑跑就好了。

AC代码如下:

#include<iostream>
#include<cstdio>
#include<map>
#include<cstring>
#define N 40005
using namespace std;

int n,m,cnt,tot,dfsclk,fst[N],pnt[N],nxt[N],pos[N],low[N],stk[N],tp,scc[N],sum[N];
struct stg{
	char ch[10];
	void read(){ scanf("%s",ch); }
}s;
bool operator <(stg a,stg b){
	int len1=strlen(a.ch),len2=strlen(b.ch),i;
	for (i=0; i<len1 && i<len2; i++){
		if (a.ch[i]<b.ch[i]) return 1; if (a.ch[i]>b.ch[i]) return 0;
	}
	return len1<len2;
}
map<stg,int> mp1,mp2;
void add(int x,int y){
	pnt[++tot]=y; nxt[tot]=fst[x]; fst[x]=tot;
}
void dfs(int x){
	pos[x]=low[x]=++dfsclk; stk[++tp]=x; int p;
	for (p=fst[x]; p; p=nxt[p]){
		int y=pnt[p];
		if (!pos[y]){
			dfs(y); low[x]=min(low[x],low[y]);
		} else if (!scc[y]) low[x]=min(low[x],pos[y]);
	}
	if (low[x]==pos[x])
		for (cnt++; ; ){
			scc[stk[tp]]=cnt; sum[cnt]++;
			if (stk[tp--]==x) break;
		}
}
int main(){
	scanf("%d",&n); int i,x,y;
	for (i=1; i<=n; i++){
		s.read(); mp1[s]=i;
		s.read(); mp2[s]=i;
	}
	scanf("%d",&m);
	while (m--){
		s.read(); x=mp1[s];
		s.read(); y=mp2[s]; add(x,y);
	}
	for (i=1; i<=n; i++){
		if (!pos[i]) dfs(i);
		puts((sum[scc[i]]>1)?"Unsafe":"Safe");	
	}
	return 0;
}


by lych

2016.3.26

你可能感兴趣的:(DFS,强连通分量)