第一题
luoguP1407
我们已知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是不安全的)。
输入输出样例
输入 #1
3 1 2 3 3 1 2 2 3 3 2
输出 #1
3 1
输入 #2
3 10 20 10 4 1 2 1 3 3 1 2 1
输出 #2
10 2
说明/提示
对于所有的数据,1<=n<=100,1<=m<=400;
大水题。。。
就是建图的地方有一点的麻烦。
其实对于每一对的夫妻,我们将他们的男方连接到女方。
对于每一对情侣,我们将他们的女方连接到男方
为什么呢?
题目原意其实是无向边。
我们发现,无向边非常的不好做,因为夫妻之间的关系是否稳定其实在于一方能否通过其他的方法影响到另一边。
emmmmmm
可能有点绕口。。。
其实意思就是,夫妻之间如果没有相互联通,能否相互到达。。。
这不就是一个赤裸裸的环吗。。。。
tarjan判环就好了啊awa
AC!awa
code
#include<bits/stdc++.h> #define ll long long using namespace std; map<string,int> h; int n,m,tot,head[100001],cnt,dfn[100001],low[1000001],ccs,dfsc,color[1000001];bool vis[100001]; struct edge { int next,to; }e[100001]; stack<int> stk; inline ll read() { char c=getchar();ll a=0,b=1; for(;c<'0'||c>'9';c=getchar())if(c=='-')b=-1; for(;c>='0'&&c<='9';c=getchar())a=a*10+c-48; return a*b; } void add(int i,int j) { e[++tot].next=head[i]; e[tot].to=j; head[i]=tot; } void tarjan(int x,int fa) { dfn[x]=low[x]=++dfsc; stk.push(x);vis[x]=true; for(int i=head[x];i!=0;i=e[i].next) { int u=e[i].to; if(u==fa)continue; if(dfn[u]==0) { tarjan(u,x); low[x]=min(low[x],low[u]); } else if(vis[u]==true) { low[x]=min(low[x],dfn[u]); } } if(dfn[x]==low[x]) { ccs++; do { color[x]=ccs; x=stk.top();stk.pop(); vis[x]=false; } while(low[x]!=dfn[x]); } } int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); n=read(); for(int i=1;i<=n;i++) { string s1,s2; cin>>s1>>s2; h[s1]=i;h[s2]=i+n;//为了后面更方便的判断夫妻之间是否有环,我们将一对夫妻编辑为i和i+n add(h[s1],h[s2]); } m=read(); for(int i=1;i<=m;i++) { string s1,s2; cin>>s1>>s2; add(h[s2],h[s1]); } for(int i=1;i<=n;i++) { if(dfn[i]==0)tarjan(i,-1); } int colo=color[1];bool flag=false; for(int i=1;i<=n;i++) { if(color[i]==color[i+n])//找环 { cout<<"Unsafe"<<endl; } else { cout<<"Safe"<<endl; } } return 0; }
the end