BZOJ2140: 稳定婚姻

【传送门:BZOJ2140


简要题意:

  给出n对夫妻和他们的名字,和m对曾经互相喜欢的男女

  如果第i对夫妻发生争吵,那么这对夫妻会各自找自己喜欢的男女求安慰,而被找到的男女的另一半会因为嫉妒,也去找自己喜欢的男女求安慰,如此循环

  如果第i对夫妻发生争吵后,仍能组成n对男女,那么这段婚姻是不安全的,否则是安全的

  判断每一对夫妻的婚姻是否安全


题解:

  二分图匹配(第一眼),O(nm)的复杂度,不要你了

  想其他方法,用强联通做

  对于原配,女连向男,对于曾经,男连向女,然后如果第i对夫妻在同一个连通块里就说明是不安全的(可以自己想一想)


参考代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
struct trie
{
    int c[75],s;
    trie()
    {
        s=0;
        memset(c,-1,sizeof(c));
    }
}t[81000];int tot;
struct node
{
    int x,y,next;
}a[31000];int len,last[8100];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}
char st[9];
void bt(int d)
{
    int len=strlen(st+1),x=0;
    for(int i=1;i<=len;i++)
    {
        int y;
        if('a'<=st[i]&&st[i]<='z') y=st[i]-'a'+1+26;
        else y=st[i]-'A'+1;
        if(t[x].c[y]==-1) t[x].c[y]=++tot;
        x=t[x].c[y];
    }
    t[x].s=d;
}
int findid()
{
    int len=strlen(st+1),x=0;
    for(int i=1;i<=len;i++)
    {
        int y;
        if('a'<=st[i]&&st[i]<='z') y=st[i]-'a'+1+26;
        else y=st[i]-'A'+1;
        x=t[x].c[y];
    }
    return t[x].s;
}
int dfn[8100],low[8100],id;
int belong[8100],s;
int sta[8100],tp;
bool v[8100];
void dfs(int x)
{
    dfn[x]=low[x]=++id;
    sta[++tp]=x;v[x]=true;
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(dfn[y]==0)
        {
            dfs(y);
            low[x]=min(low[x],low[y]);
        }
        else
        {
            if(v[y]==true) low[x]=min(low[x],dfn[y]);
        }
    }
    if(low[x]==dfn[x])
    {
        s++;int i;
        do
        {
            i=sta[tp--];
            belong[i]=s;
            v[i]=false;
        }while(i!=x);
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    tot=0;
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=n;i++)
    {
        scanf("%s",st+1);bt(2*i-1);
        scanf("%s",st+1);bt(2*i);
        ins(2*i,2*i-1);
    }
    int m;scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int x,y;
        scanf("%s",st+1);x=findid();
        scanf("%s",st+1);y=findid();
        ins(x,y);
    }
    memset(v,false,sizeof(v));
    tp=id=s=0;
    memset(dfn,0,sizeof(dfn));
    for(int i=1;i<=2*n;i++)
    {
        if(dfn[i]==0) dfs(i);
    }
    for(int i=1;i<=n;i++)
    {
        if(belong[2*i-1]==belong[2*i]) printf("Unsafe\n");
        else printf("Safe\n");
    }
    return 0;
}

 

posted @ 2018-03-23 19:55  Star_Feel  阅读(184)  评论(0编辑  收藏  举报