[Luogu] 稳定婚姻

https://www.luogu.org/problemnew/show/1407

tarjan求一下强连通分量,然后判断一下两个人是否在同一强连通分量中

#include<iostream>
#include<cstring>
#include<cstdio>
#include<map>

using namespace std;

inline int read() {
    int sum(0);
    char ch(getchar());
    for(; ch<'0'||ch>'9'; ch=getchar());
    for(; ch>='0'&&ch<='9'; sum=sum*10+(ch^48),ch=getchar());
    return sum;
}

struct edge {
    int e;
    edge *n;
    edge():e(0),n(NULL) {}
} a[40005],*pre[8005];

int tot;

inline void insert(int s,int e) {
    a[++tot].e=e;
    a[tot].n=pre[s];
    pre[s]=&a[tot];
}

int n,m;
char s1[10],s2[10];
map<string,int>ma;
int cnt,top,qlt;
int dfn[8005],low[8005],sta[8005],bl[8005];
bool vis[8005];

inline void tarjan(int u) {
    dfn[u]=low[u]=++cnt;
    sta[++top]=u;
    vis[u]=1;
    for(edge *i=pre[u]; i; i=i->n) {
        int e(i->e);
        if(!dfn[e]) {
            tarjan(e);
            low[u]=min(low[u],low[e]);
        } else if(vis[e])
            low[u]=min(low[u],dfn[e]);
    }
    if(low[u]==dfn[u]) {
        int tmp;
        ++qlt;
        while(1) {
            tmp=sta[top--];
            vis[tmp]=0;
            bl[tmp]=qlt;
            if(tmp==u)
                break;
        }
    }
}

int main() 
{
    memset(pre,NULL,sizeof(pre));
    n=read();
    for(int i=1; i<=n; ++i) {
        scanf("%s%s",s1,s2);
        insert((i<<1)-1,i<<1);
        ma[s1]=(i<<1)-1,ma[s2]=i<<1;
    }
    m=read();
    for(int i=1; i<=m; ++i) {
        scanf("%s%s",s1,s2);
        insert(ma[s2],ma[s1]);
    }
    for(int i=1; i<=(n<<1); ++i) if(!dfn[i]) tarjan(i);
    for(int i=1; i<=n; ++i)
        if(bl[(i<<1)-1]==bl[i<<1]) puts("Unsafe");
        else puts("Safe");
    return 0;
}
原文地址:https://www.cnblogs.com/shandongs1/p/8298780.html