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

传送门

题外话:恭喜lgr大佬rank4

题目背景
原《工资》重题请做2397

题目描述
我国的离婚率连续7年上升,今年的头两季,平均每天有近5000对夫妇离婚,大城市的离婚率上升最快,有研究婚姻问题的专家认为,是与简化离婚手续有关。

25岁的姗姗和男友谈恋爱半年就结婚,结婚不到两个月就离婚,是典型的“闪婚闪离”例子,而离婚的导火线是两个人争玩电脑游戏,丈夫一气之下,把电脑炸烂。

有社会工作者就表示,80后求助个案越来越多,有些是与父母过多干预有关。而根据民政部的统计,中国离婚五大城市首位是北京,其次是上海、深圳,广州和厦门,那么到底是什么原因导致我国成为离婚大国呢?有专家分析说,中国经济急速发展,加上女性越来越来越独立,另外,近年来简化离婚手续是其中一大原因。

——以上内容摘自第一视频门户

现代生活给人们施加的压力越来越大,离婚率的不断升高已成为现代社会的一大问题。而其中有许许多多的个案是由婚姻中的“不安定因素”引起的。妻子与丈夫吵架后,心如绞痛,于是寻求前男友的安慰,进而夫妻矛盾激化,最终以离婚收场,类似上述的案例数不胜数。

我们已知n对夫妻的婚姻状况,称第i对夫妻的男方为Bi,女方为Gi。若某男Bi与某女Gj曾经交往过(无论是大学,高中,亦或是幼儿园阶段,i≠j),则当某方与其配偶(即Bi与Gi或Bj与Gj)感情出现问题时,他们有私奔的可能性。不妨设Bi和其配偶Gi感情不和,于是Bi和Gj旧情复燃,进而Bj因被戴绿帽而感到不爽,联系上了他的初恋情人Gk……一串串的离婚事件像多米诺骨牌一般接踵而至。若在Bi和Gi离婚的前提下,这2n个人最终依然能够结合成n对情侣,那么我们称婚姻i为不安全的,否则婚姻i就是安全的。

给定所需信息,你的任务是判断每对婚姻是否安全。

输入格式
第一行为一个正整数n,表示夫妻的对数;

以下n行,每行包含两个字符串,表示这n对夫妻的姓名(先女后男),由一个空格隔开;

第n+2行包含一个正整数m,表示曾经相互喜欢过的情侣对数;

以下m行,每行包含两个字符串,表示这m对相互喜欢过的情侣姓名(先女后男),由一个空格隔开。

输出格式
输出文件共包含n行,第i行为“Safe”(如果婚姻i是安全的)或“Unsafe”(如果婚姻i是不安全的)。

题解:
考虑一对夫妻是不安全的情况下,他们必然再一个环中,因为tarjan只能解决有向图的问题,那么我们把正常的婚姻以女->男的方式连,绿帽子的情况反过来连,这样就能形成一个人体蜈蚣 环,然后我们判断没对夫妻是否再一个强连通分量中即可。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <map>
using namespace std;
const int M=25000;
int n,m,tot,head[M],to[M],nex[M],dfn[M],sta[M],idx,top,cnt,bel[M],low[M];
bool vis[M]; 
map<string,int>lgr;
string a,b;//a是妹子,b是 男的 
inline int read(){
   
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
   if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){
   x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline void add(int x,int y){
   
	++tot;
	nex[tot]=head[x];
	to[tot]=y;
	head[x]=tot;
}
inline int Tarjan(int u){
   
	dfn[u]=low[u]=++idx;
	vis[u]=1;
	sta[++top]=u;
	for(int i=head[u];i;i=nex[i]){
   
		  int dmf=to[i];
		  if(!dfn[dmf]){
   
		  	   Tarjan(dmf);
		  	   low[u]=min(low[u],low[dmf]);
		  }
		  else if(vis[dmf]) low[u]=min(low[u],low[dmf]);
	}
	if(dfn[u]==low[u]){
   
		++cnt;
		bel[u]=cnt;
		vis[u]=0;
		while(sta[top]!=u){
   
			bel[sta[top]]=cnt;
			vis[sta[top--]]=0;
		}
		top--;
	}
}
int main(){
   
	n=read();
	for(int i=1;i<=n;i++){
   
		cin>>a>>b;
		lgr[a]=i;
		lgr[b]=i+n;
		add(i,i+n);
	}
	m=read();
	for(int i=1;i<=m;i++){
   
		cin>>a>>b;
		add(lgr[b],lgr[a]);
	}
	for(int i=1;i<=n*2;i++){
   
		if(!dfn[i]){
   
			Tarjan(i);
		}
	}
	for(int i=1;i<=n;i++){
   
		if(bel[i]==bel[i+n])puts("Unsafe");
		else puts("Safe");
	}
	return 0;
} 

注意!此信息未认证,请谨慎判断信息的真实性!

全部评论
空

相关内容推荐

头像
点赞 评论 收藏
转发
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像 头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
点赞 评论 收藏
转发
头像 头像
点赞 评论 收藏
转发
头像 头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像 头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
头像
点赞 评论 收藏
转发
点赞 收藏 评论
分享

全站热榜

正在热议