二分图匹配

来源:互联网 发布:ei数据库怎么进入 编辑:程序博客网 时间:2024/06/05 11:12

HDU  2063

 求一个二分图的最大匹配。

完全的裸题。贴代码。

#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>#include<iostream>using namespace std;vector<int> G[1005];bool check[1005];int mac[1005];int n;void add_edge(int from,int to){    G[from].push_back(to);    G[to].push_back(from);}bool dfs(int u){    for(int i=0;i<G[u].size();i++)    {        int v=G[u][i];        if(!check[v])        {            check[v]=1;            if(mac[v]==-1||dfs(mac[v]))            {                mac[u]=v;                mac[v]=u;                return 1;            }        }    }    return 0;}int xyl(){    int ans=0;    memset(mac,-1,sizeof(mac));    for(int i=1;i<=n;i++)    {        if(mac[i]==-1)        {            memset(check,0,sizeof(check));            if(dfs(i))            {                ans++;            }        }    }    return ans;}int main(){    int k,n1,m1;    while(scanf("%d",&k)!=EOF)    {        if(k==0) return 0;        scanf("%d%d",&n1,&m1);        n=n1+m1;        for(int i=1;i<=n;i++)            G[i].clear();        while(k--)        {            int A,B;            scanf("%d%d",&A,&B);            add_edge(A,B+n1);        }        printf("%d\n",xyl());    }}

HDU 2444

判断该图是否为二分图,如果是二分图就求该图的最大匹配。

判断是否为二分图是我用了一个DFS 也不知道还有没有更简单的方法。

#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>#include<stack>#include<math.h>#include<iostream>using namespace std;vector<int> G[205];bool check[205];int mac[205];int re[205];void add_edge(int from,int to){    G[from].push_back(to);    G[to].push_back(from);}bool rdfs(int u,int k){    re[u]=k;    bool flag=true;    int k1;    if(k==1) k1=2;    else k1=1;    for(int i=0;i<G[u].size();i++)    {        int v=G[u][i];        if(re[v]==k)        {            flag=false;            break;        }        else if(re[v]==0)        {            flag=rdfs(v,k1);            if(!flag)                break;        }    }    return flag;}bool dfs(int u){    for(int i=0;i<G[u].size();i++)    {        int v=G[u][i];        if(!check[v])        {            check[v]=true;            if(mac[v]==-1||dfs(mac[v]))            {                mac[u]=v;                mac[v]=u;                return true;            }        }    }    return false;}int n;int xyl(){    int ans=0;    memset(mac,-1,sizeof(mac));    for(int i=1;i<=n;i++)    {        if(mac[i]==-1)        {            memset(check,0,sizeof(check));            check[i]=1;            if(dfs(i))                ans++;        }    }    return ans;}int main(){    int m;    while(scanf("%d%d",&n,&m)!=EOF)    {        for(int i=1;i<=n;i++)            G[i].clear();        while(m--)        {            int A,B;            scanf("%d%d",&A,&B);            add_edge(A,B);        }        memset(re,0,sizeof(re));        bool flag=0;        for(int i=1;i<=n;i++)        {            if(re[i]==0)            {                if(!rdfs(i,1))                {                    flag=1;                    break;                }            }        }        if(flag==1) printf("No\n");        else        {            printf("%d\n",xyl());        }    }}

HDU 1281

题意:一个棋盘上有一些地方能放“车” 求最多能放多少个,又有多少个点是关键点,关键点——删除这个点能放的“车”会变少。

把行归位X集合 列归为Y集合。每个点就是从X-Y的一条边。

进行二分图匹配。然后枚举边,求出删除这条边之后的最大匹配,如果比之前的少了 就是关键点。

#include<stdio.h>#include<string.h>#include<algorithm>#include<vector>#include<iostream>using namespace std;int mac[205];bool check[205];vector<int> G[205];int z,y;int n;int k[10005][2];void add_edge(int from,int to){    G[from].push_back(to);    G[to].push_back(from);}bool dfs(int u){    for(int i=0;i<G[u].size();i++)    {        int v=G[u][i];        if((u==z&&v==y)||(u==y&&v==z)) continue;        if(!check[v])        {            check[v]=1;            if(mac[v]==-1||dfs(mac[v]))            {                mac[u]=v;                mac[v]=u;                return true;            }        }    }    return false;}int xyl(){    memset(mac,-1,sizeof(mac));    int ans=0;    for(int i=1;i<=n;i++)    {        if(mac[i]==-1)        {            memset(check,0,sizeof(check));            if(dfs(i))                ans++;        }    }    return ans;}int main(){    int N,M,K;    int Case=0;    while(scanf("%d%d%d",&N,&M,&K)!=EOF)    {        for(int i=1;i<=N+M;i++)            G[i].clear();            int r=0;            n=N+M;        while(K--)        {            int A,B;            scanf("%d%d",&A,&B);            k[r][0]=A;            k[r][1]=B+N;            r++;            add_edge(A,B+N);        }        z=0;y=0;        int ans=xyl();        //printf("%d\n",ans);        int sum=0;        for(int i=0;i<r;i++)        {            z=k[i][0];            y=k[i][1];            int ans1=xyl();            if(ans1!=ans)            {                sum++;            }        }        printf("Board %d have %d important blanks for %d chessmen.\n",++Case,sum,ans);    }}


0 0