您的位置:首页 > 其它

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

2015-03-10 21:26 519 查看
二分图匹配。

左边的点表示属性,右边的点表示武器编号,每次读入将武器和对应属性之间连边,然后从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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: