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

来源:互联网 发布:淘宝云建站不能用了吗 编辑:程序博客网 时间:2024/06/08 08:29

二分图匹配。 

左边的点表示属性,右边的点表示武器编号,每次读入将武器和对应属性之间连边,然后从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
原创粉丝点击