BZOJ P2140稳定婚姻

一开始看到题目以为是二分图匹配直接上

但是显然是会T的呀

一条边一条边删过去然后跑二分图匹配,再加上2s的时限

一看就很玄学

然后你画图你会发现

如果一对夫妻在同一个强连通分量时,显然是Unsafe的

画图很明显,就是类似于每一个原配都可以被环上的下一个点所替代,然后形成的环上的每一个点都可以被下一个点替代

然后不再环上的点直接和原配就可以了

然后就直接tarjan就可以了

get了一个新技能,判断某一二分图是否能完全匹配时可以不用暴力匈牙利,可以用tarjan

然后下面是代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<map>
using namespace std;
int n,m,col,tot,cnt,x[2003],y[2003];
stack<int> s;
map<string,int> name;
int color[100003],low[100003],dfn[100003];
int inst[100003];
int to[100003],nex[100003],head[100003];
void add(int u,int v){
	to[++tot]=v;
	nex[tot]=head[u];
	head[u]=tot;
}
void tarjan(int node){
	dfn[node]=++cnt;
	low[node]=cnt;
	s.push(node);
	inst[node]=1;
	for(int i=head[node];i;i=nex[i]){
		int t=to[i];
		if(!dfn[t]){
			tarjan(t);
			low[node]=min(low[node],low[t]);
		}
		if(inst[t]==1){
			low[node]=min(low[node],dfn[t]);
		}
	}
	if(low[node]==dfn[node]){
		col++;
		while(s.top()!=node){
			color[s.top()]=col;inst[s.top()]=2;
			s.pop();
		}
		color[node]=col;inst[node]=2;
		s.pop();
	}
}
void doit(){
	cnt=col=0;
	memset(inst,0,sizeof(inst));
	for(int i=1;i<=2*n;i++){
		if(!inst[i]){
			tarjan(i);
		}
	}
	for(int i=1;i<=n;i++){
		if(color[i]==color[i+n]){
			cout<<"Unsafe"<<endl;
		}else{
			cout<<"Safe"<<endl;
		}
	}
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		string wife,husband;
		cin>>wife>>husband;
		name[wife]=i;
		name[husband]=i+n;
		add(i,n+i);
	}
	cin>>m;
	for(int i=1;i<=m;i++){
		string gf,bf;
		cin>>gf>>bf;
		add(name[bf],name[gf]);
	}
	doit();
	return 0;
}
/*
in1:
2
Melanie Ashley
Scarlett Charles
1
Scarlett Ashley
out1:
Safe
Safe

in2:
2
Melanie Ashley
Scarlett Charles
2
Scarlett Ashley
Melanie Charles

out2:
Unsafe
Unsafe
*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值