#Tarjan#洛谷 1407 [国家集训队]稳定婚姻

题目


分析

如果婚姻安全那么两个点不在同一个强连通分量,
考虑强制定方向,夫妻女向男连边,情侣男向女连边,
这样就直接用Tarjan有向图缩点就可以了


代码

#include <iostream>
#include <string>
#include <stack>
#include <map>
#define rr register
using namespace std;
const int N=8011; stack<int>stac; map<string,int>uk;
struct node{int y,next;}e[N<<2]; string S,T;
int as[N],low[N],dfn[N],col[N],k,v[N],n,tot,cnt,m;
inline void add(int x,int y){e[++k]=(node){y,as[x]},as[x]=k;}
inline void tarjan(int x){
	dfn[x]=low[x]=++tot;
	stac.push(x); v[x]=1;
	for (rr int i=as[x];i;i=e[i].next)
	if (!dfn[e[i].y]){
		tarjan(e[i].y);
		low[x]=min(low[x],low[e[i].y]);
	}
	else if (v[e[i].y])
	    low[x]=min(low[x],dfn[e[i].y]);
	if (dfn[x]==low[x]){
		++cnt; rr int y;
		do{
			y=stac.top(); stac.pop();
			v[y]=0; col[y]=cnt;
		}while (x!=y);
	}
}
signed main(){
	ios::sync_with_stdio(0),
	cin.tie(0),cout.tie(0);
	cin>>n;
	for (rr int i=1;i<=n;++i)
		cin>>S>>T,add(uk[S]=i,uk[T]=i+n);
	cin>>m;
	for (rr int i=1;i<=m;++i)
		cin>>S>>T,add(uk[T],uk[S]);
	for (rr int i=1;i<=n*2;++i)
	    if (!dfn[i]) tarjan(i);
	for (rr int i=1;i<=n;++i)
	if (col[i]^col[i+n]) cout<<"Safe"<<endl;
	    else cout<<"Unsafe"<<endl;
	return 0;
}
原文地址:https://www.cnblogs.com/Spare-No-Effort/p/13922246.html