[BZOJ 1854] SCOI 2010 游戏 · 二分图匹配

二分图匹配。 

左边的点表示属性,右边的点表示武器编号,每次读入将武器和对应属性之间连边,然后从1-10000枚举属性值,如果某个属性值没有匹配到武器那么就退出循环,输出上一个属性值。为了防止第10000属性也可以满足,要枚举到10001。另外笔者蒟蒻……第一遍交跑出个TLE,然后重新看了一下匈牙利发现,我们把vis数组的职能从bool类型改成了int类型,对于第k个属性值,每次访问到一个武器i时,如果vis[i]==k就说明本次搜索这个点已经搜过了,否则记录一下vis[i]=k,防止重复搜索,这样就可以不要每次都memset。

#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;

const int maxn=5000005;
int n,m,match[maxn],vis[maxn],x,y,k;
int node[maxn],next[maxn],head[maxn],tot;

int get(){
    int p=0;char x=getchar();
    while (x<'0' && x>'9') x=getchar();
    while (x>='0' && x<='9') p=p*10+x-'0',x=getchar();
    return p;
}

void add(int x,int y){
	node[++tot]=y;
    next[tot]=head[x];
    head[x]=tot;
}

bool dfs(int x){
    for (int i=head[x];i;i=next[i])
        if (vis[node[i]]!=k){
            vis[node[i]]=k;
            if (!match[node[i]] || dfs(match[node[i]])){
                match[node[i]]=x;
                return 1;
            }
        }
    return 0;
}

int main(){
    n=get();tot=0;
    memset(head,0,sizeof head);
    memset(vis,0,sizeof vis);
    for (int i=1;i<=n;i++){
        x=get();y=get();
        add(x,i);add(y,i);
    }
    for (k=1;k<=10001;k++)
        if (!dfs(k)) break;
    printf("%d",k-1);
    return 0;
}


 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值