朋友(强连通)
我们已知 n 对男女朋友,称第 i 对朋友的男方为 B(i),女方为 G(i)。若某男 B(i) 与某女 G(j) 曾经是同学(无论是大学,高中,亦或是幼儿园阶段,i <=j),则当某方与其朋友(即 B(i) 与 G(i) 或 B(j) 与 G(j))感情出现问题时,他们有私奔的可能性。不妨设 B(i) 和其配偶 G(i) 感情不和,于是 B(i) 和 G(j) 旧情复燃,进而 B(j) 因被戴绿帽而感到不爽,联系上了他的初恋情人 G(k) ……一串串的分手事件像多米诺骨牌一般接踵而至。若在 B(i) 和 G(i) 离婚的前提下,这 2n 个人最终依然能够结合成 n 对情侣,那么我们称第 i对 为不安全的,否则 i 就是安全的。
给定所需信息,你的任务是判断每对是否安全。
输入格式
第一行为一个正整数 n,表示男女朋友的对数;
以下 n 行,每行包含两个字符串,表示这 n 对男女朋友的姓名(先女后男),由一个空格隔开;
第 n+2 行包含一个正整数 m,表示曾经相互喜欢过的情侣对数;
以下 m 行,每行包含两个字符串,表示这 m 对相互喜欢过的情侣姓名(先女后男),由一个空格隔开。
所有姓名字符串中只包含英文大小写字母,大小写敏感,长度不大于 8,保证每对关系只在输入文件中出现一次,输入文件的最后 m 行不会出现未在之前出现过的姓名,这 2n 个人的姓名各不相同,1 <=n<= 4000,0 <=m<= 20000。
输出格式
输出文件共包含 n 行,第 i 行为 `Safe`(如果第i对 是安全的)或 `Unsafe`(如果婚姻 i 是不安全的)。
输入/输出例子1
输入:
2
Melanie Ashley
Scarlett Charles
1
Scarlett Ashley
输出:
Safe
Safe
样例解释
无
题目有点绕,化简一下。画个图好理解

设A代表女,B代表男,根据题意,可以整理成上图所示
那么就是2个组合 {B1, A2},{B2,A3}, 此时还有两个单身,要形成稳定婚姻,只能是 {B3,A1}。
那么可以发现此时就是一个强连通,也就是环,图中每一个点都可以到另外一个点,因为只有这样,图中的每一个人即使丢失现有配偶,也有他的配偶可选
那么我们考虑找强连通即可。
注意考虑建边的方向,如果是现在的夫妻关系,那么应该是A->B,即女到男,如果是之前的情侣关系,那么应该是B->A,即男到女,这样才能保住连通
A,B同一个强连通,不安全
不同一个, 安全
建图,特别是建边需要好好考虑,不能上来就建无向边/有向边,搞清楚点与点的关系,再去建边
#include <bits/stdc++.h>
using namespace std;
const int N=4e4+5;
int n, m;
map<string, int> mp;
string u1, v1, g[N], b[N];
int tem=0, dfn[N], low[N], idx=0, cnt=0, id[N];
vector<int> a[N];
stack<int> st;
void dfs(int u)
{
dfn[u]=low[u]=++idx;
st.push(u);
for (int i=0; i<a[u].size(); i++)
{
int v=a[u][i];
if (!dfn[v])
{
dfs(v);
low[u]=min(low[u], low[v]);
}
else if (!id[v]) low[u]=min(low[u], dfn[v]);
}
if (low[u]==dfn[u])
{
cnt++;
while (st.top()!=u)
{
id[st.top()]=cnt;
st.pop();
}
id[st.top()]=cnt;
st.pop();
}
}
int main()
{
scanf("%d", &n);
for (int i=1; i<=n; i++)
{
cin>>u1>>v1;
g[i]=u1, b[i]=v1;
mp[u1]=++tem, mp[v1]=++tem;
a[mp[u1]].push_back(mp[v1]);
}
scanf("%d", &m);
for (int i=1; i<=m; i++)
{
cin>>u1>>v1;
a[mp[v1]].push_back(mp[u1]);
}
for (int i=1; i<=tem; i++)
if (!dfn[i]) dfs(i);
for (int i=1; i<=n; i++)
{
if (id[mp[g[i]]]==id[mp[b[i]]]) printf("Unsafe\n");
else printf("Safe\n");
}
return 0;
}

浙公网安备 33010602011771号