BZOJ1191 [HNOI2006]超级英雄Hero 二分图匹配

欢迎访问~原文出处——博客园-zhouzhendong

去博客园看该题解


题目传送门 - BZOJ1191


题目概括

  有m个题目,有n个解决方案;对于每一个题目,有两种解决方案可用。

  每种解决方案只能用一次,问最多可以通过最前面的几题?


 

题解

  几乎是裸的二分图匹配。

  每个题目两条边,分别连向所对应的两种解决方案。

  然后跑匈牙利算法。具体可以看这里,往后翻就有匈牙利算法的解说。

  可怕的是,我之前以为是最多可以通过几道。

  白白wa了很久……

  其实是从第一题开始,最多可以连续通过几道。


代码

#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=2000+5,M=N;
struct Gragh{
    int cnt,x[M],y[M],nxt[M],fst[N];
    void set(){
        cnt=0;
        memset(fst,0,sizeof fst);
    }
    void add(int a,int b){
        x[++cnt]=a,y[cnt]=b;
        nxt[cnt]=fst[a],fst[a]=cnt;
    }
}g;
int n,m,cnt,vis[N],match[N];
bool dfs(int x){
    for (int i=g.fst[x];i;i=g.nxt[i])
        if (!vis[g.y[i]]){
            vis[g.y[i]]=1;
            if (match[g.y[i]]==-1||dfs(match[g.y[i]])){
                match[g.y[i]]=x;
                return 1;
            }
        }
    return 0;
}
int main(){
    scanf("%d%d",&n,&m);
    g.set();
    memset(match,-1,sizeof match);
    cnt=0;
    for (int i=1,a,b;i<=m;i++){
        scanf("%d%d",&a,&b);
        a++,b++;
        g.add(i,m+a);
        g.add(i,m+b);
        memset(vis,0,sizeof vis);
        if (dfs(i))
            cnt++;
        else
            break;
    }
    printf("%d",cnt);
    return 0;
}

 

posted @ 2017-08-17 14:59  zzd233  阅读(258)  评论(0编辑  收藏  举报