bzoj 2140: 稳定婚姻

查询二分图每一条边是否一定在二分图最大匹配上:
首先任意一个最大匹配,然后把两个匹配点缩成一个点,然后用这个图跑强连通分量,如果一个点所在的强连通分量大小大于1,那么说明原图存在一条匹配边-非匹配边-匹配边-非匹配边的环,所以这些边不一定在最大匹配上。
     
    
    
    
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<map>
#define ll long long
#define unl unsigned long long
#define inf 1e9
#define eps 1e-8
#define md
#define N 4010
using namespace std;
struct yts { int x,t,ne;} e[20010];
int dfn[N],low[N],s[N],v[N],scc[N],sz[N];
char st[N];
const unl cheng=2333;
int num,dfs_cnt,top,scc_cnt;
map<unl,int> mp;
void put(int x,int y)
{
num++; e[num].x=x; e[num].t=y;
e[num].ne=v[x]; v[x]=num;
}
 
unl get_hash()
{
int l=strlen(st+1);
unl ans=0;
for (int i=1;i<=l;i++) ans=ans*cheng+(unl)st[i];
return ans;
}
 
void tarjan(int x)
{
dfn[x]=low[x]=++dfs_cnt; s[++top]=x;
for (int i=v[x];i;i=e[i].ne)
{
int y=e[i].t;
if (!dfn[y])
{
tarjan(y);
low[x]=min(low[x],low[y]);
}
else if (!scc[y]) low[x]=min(low[x],dfn[y]);
}
if (dfn[x]==low[x])
{
scc_cnt++;
int y;
do
{
y=s[top--];
scc[y]=scc_cnt;
sz[scc_cnt]++;
} while (y!=x);
}
}
 
int main()
{
int n,m;
scanf("%d",&n);
for (int i=1;i<=n;i++)
{
scanf("%s",st+1);
unl ha=get_hash();
mp[ha]=i;
scanf("%s",st+1);
ha=get_hash();
mp[ha]=i;
}
scanf("%d",&m);
for (int i=1;i<=m;i++)
{
scanf("%s",st+1);
unl ha=get_hash();
int a=mp[ha];
scanf("%s",st+1);
ha=get_hash();
int b=mp[ha];
put(a,b);
}
for (int i=1;i<=n;i++) if (!dfn[i]) tarjan(i);
for (int i=1;i<=n;i++)
if (sz[scc[i]]!=1) printf("Unsafe\n");
else printf("Safe\n");
return 0;
}


你可能感兴趣的:(bzoj 2140: 稳定婚姻)