P1407 [国家集训队]稳定婚姻 Tarjan

题意:

题面过长,实在没法一句话题意,自己看吧

戳这里,查看题面

分析:

这题好像是挺板子的,我们考虑不稳定的婚姻是什么样子的,就是每个人都可以找到一个特定的人与之配对,我们把配偶关系和配对关系看成等价的,然后连边,画成图的话就像一个有向的环,也就是说不稳定的婚姻存在于一个强连通分量里,那么就先哈希把人名转化成编号,在Tarjan求一遍强联通分量,看一看每一对夫妻是否在同一个强连通分量里面,若是则婚姻是不稳定的

代码:

#include<bits/stdc++.h>

using namespace std;

namespace zzc
{
	const int maxn = 40005;
	map<string,int> mp;
	int n,m,cnt=0,num=0;
	int head[maxn];
	
	struct edge
	{
		int to,nxt;
	}e[maxn<<1];
	
	void add(int u,int v)
	{
		e[++cnt].to=v;
		e[cnt].nxt=head[u];
		head[u]=cnt;
	}
	
	bool vis[maxn];
	int st[maxn],top=0,dfn[maxn],low[maxn],tim=0,belong[maxn],scc=0;
	void tarjan(int u)
	{
		dfn[u]=low[u]=++tim;
		st[++top]=u;
		vis[u]=true;
		for(int i=head[u];i;i=e[i].nxt)
		{
			int v=e[i].to;
			if(!dfn[v])
			{
				tarjan(v);
				low[u]=min(low[u],low[v]);
			}
			else if(vis[v])
			{
				low[u]=min(low[u],dfn[v]);
			}
		}
		if(low[u]==dfn[u])
		{
			scc++;
			do
			{
				int v=st[top];
				vis[v]=false;
				belong[v]=scc;
			}
			while(st[top--]!=u);
		}
	}
	
	void work()
	{
		string a,b;
		cin>>n;
		for(int i=1;i<=n;i++)
		{
			cin>>a>>b;
			mp[a]=i;
			mp[b]=i+n;
			add(i,i+n);
		}
		cin>>m;
		for(int i=1;i<=m;i++)
		{
			cin>>a>>b;
			add(mp[b],mp[a]);
		}
		for(int i=1;i<=2*n;i++)
		{
			if(!dfn[i])
			{
				tarjan(i);
			}
		}
		for(int i=1;i<=n;i++)
		{
			if(belong[i]!=belong[i+n])
			{
				printf("Safe
");
			}
			else printf("Unsafe
");
		}
	}
	
}

int main()
{
	zzc::work();
	return 0;
 } 
原文地址:https://www.cnblogs.com/youth518/p/13689337.html