求二分图完备匹配的必要边,①存不存在增广环? O(N^2) ②直接试着删去按照hungery找完备匹配 O(N^3)。
如果一个点所在的强连通分量大小大于1,那么说明原图存在一条匹配边-非匹配边-匹配边-非匹配边的环,所以这些边不一定在最大匹配上。
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<map>
#define V G[p].v
using namespace std;
struct edge{
int u,v,next;
};
edge G[400005];
int head[10005],inum;
inline void add(int u,int v,int p)
{
G[p].u=u; G[p].v=v; G[p].next=head[u]; head[u]=p;
}
int scc[10005],cnt;
int Stk[10005],pnt;
int pre[10005],low[10005],clk;
inline void dfs(int u)
{
pre[u]=low[u]=++clk; Stk[++pnt]=u;
for (int p=head[u];p;p=G[p].next)
if (!scc[V])
{
if (!pre[V])
dfs(V),low[u]=min(low[u],low[V]);
else
low[u]=min(low[u],pre[V]);
}
if (low[u]==pre[u])
{
++cnt;
while (Stk[pnt]!=u)
scc[Stk[pnt--]]=cnt;
scc[Stk[pnt--]]=cnt;
}
}
int n,m;
map<string,int> M;
int main()
{
string str;
int t1,t2;
cin>>n;
for (int i=1;i<=n;i++)
{
cin>>str; M[str]=i;
cin>>str; M[str]=i+n;
add(i,i+n,++inum);
}
cin>>m;
for (int i=1;i<=m;i++)
{
cin>>str; t1=M[str];
cin>>str; t2=M[str];
add(t2,t1,++inum);
}
for (int i=1;i<=n;i++)
if (!pre[i])
dfs(i);
for (int i=1;i<=n;i++)
if (scc[i]!=scc[i+n])
printf("Safe\n");
else
printf("Unsafe\n");
return 0;
}