Luogu P1407 [国家集训队]稳定婚姻 (二分图写法)

RT,这是一道强联通分量。
而我一个热爱匈牙利的OIer
默默敲下了...

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;

int n,m,cnt,vis[100005],match[100005],head[100005],now[100005];

map<string,int> boy,girl;

struct edge{
    int u,v,next;bool dis;
}e[100005];

inline void add(int u,int v){
    e[++cnt].v=v;
    e[cnt].u=u;
    e[cnt].next=head[u];
    head[u]=cnt;
}

inline bool dfs(int u){
    for(int i=head[u];i!=-1;i=e[i].next){
        if(e[i].dis)continue;
        int v=e[i].v;
        if(!vis[v]){
            vis[v]=1;
            if(match[v]==-1||dfs(match[v])){
                match[v]=u;
                return 1;
            }
        }
    }
    return 0;
}

int main(){
    memset(match,-1,sizeof(match));
    memset(head,-1,sizeof(head));
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        string s,t;
        cin>>s>>t;
        boy[s]=i;
        girl[t]=i;
        add(boy[s],girl[t]);
        now[i]=cnt;
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        string s,t;
        cin>>s>>t;
        add(boy[s],girl[t]);
    }
    for(int i=1;i<=n;i++){
        memset(match,-1,sizeof(match));
        int tot=0;
        e[now[i]].dis=1;
        for(int j=1;j<=n;j++){
            memset(vis,0,sizeof(vis));
            tot+=dfs(j);
        }
        if(tot==n){
            printf("Unsafe\n");
        }
        else{
            printf("Safe\n");
        }
        e[now[i]].dis=0;
    }
}

TLE事故现场

然后各种常数优化
NM的register,hash,读入优化
P用么得
然后去翻了洛谷题解
大概基本上都是强联通分量的
有一篇是二分图
然后重拾了信心QwQ
但是那位巨佬的二分图建图是把汉字和妹子统一编号的,我不习惯那样
所以抄不了题解,只好自己刚
心态崩盘后仔细研读了那位巨佬的题解
发现根!本!不!是!一般的二分图写法
因为一开始是匹配好的
用我的码风来描述就是:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;

int n,m,cnt,vis[100005],match[100005],head[100005],dis;

map<string,int> boy,girl;

struct edge{
    int u,v,next;
}e[100005];

inline void add(int u,int v){
    e[++cnt].v=v;
    e[cnt].u=u;
    e[cnt].next=head[u];
    head[u]=cnt;
}

inline bool dfs(int u){
    for(int i=head[u];i!=-1;i=e[i].next){
        int v=e[i].v;
        if(u==dis&&v==dis)continue;
        if(!vis[v]){
            vis[v]=1;
            if(match[v]==-1||dfs(match[v])){
                return 1;
            }
        }
    }
    return 0;
}

int main(){
    memset(match,-1,sizeof(match));
    memset(head,-1,sizeof(head));
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        string s,t;
        cin>>s>>t;
        boy[s]=i;
        girl[t]=i;
        match[i]=i;
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        string s,t;
        cin>>s>>t;
        add(boy[s],girl[t]);
    }
    for(int i=1;i<=n;i++){
        memset(vis,0,sizeof(vis));
        match[i]=-1;
        dis=i;
        if(dfs(i)){
            printf("Unsafe\n");
        }
        else{
            printf("Safe\n");
        }
        match[i]=i;
    }
}

AC现场

转载于:https://www.cnblogs.com/Y15BeTa/p/11298438.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值