二分图相关题

来源:互联网 发布:数据库数据模型有几种 编辑:程序博客网 时间:2024/05/29 13:26

HDU 1281

由于每行最多放一个,每列最多放一个(不能放置的位置不影响攻击,就是因为没注意这句话,把这题当做行列覆盖模型做了好久0.0)

所以把行列直接当做二分图X和Y集,可以放置的点的行列连边,求出的完备匹配就是第二个答案。

至于第一个答案求关键点,就枚举删除一条边能否任然得到完备匹配,若不行,则是关键点。

我的代码c++会WA,不知道为什么,求教啊。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int mp[105][105];int to[105];bool vis[105];int n;int dfs(int k){    for(int i=1;i<=n;i++)    {        if(!vis[i]&&mp[k][i])        {            vis[i]=1;            if(to[i]==-1||dfs(to[i]))            {                to[i]=k;                return 1;            }        }    }    return 0;}int a[100090],b[100900];int main(){    int m,k,ca=1;    while(scanf("%d%d%d",&n,&m,&k)!=EOF)    {        memset(mp,0,sizeof(mp));        for(int i=1;i<=k;i++)        {            scanf("%d%d",&a[i],&b[i]);            mp[a[i]][b[i]]=1;        }        int ans=0;        memset(to,-1,sizeof(to));        for(int i=1;i<=n;i++)        {            memset(vis,0,sizeof(vis));            ans+=dfs(i);        }        int ans2=0,tot=0;        for(int i=1;i<=k;i++)        {            ans2=0;            mp[a[i]][b[i]]=0;            memset(to,-1,sizeof(to));            for(int i=1;i<=n;i++)            {                memset(vis,0,sizeof(vis));                ans2+=dfs(i);            }            if(ans2!=ans) tot++;            mp[a[i]][b[i]]=1;        }        printf("Board %d have %d important blanks for %d chessmen.\n",ca++,tot,ans);    }    return 0;}

POJ 2062

第一个人按顺序出牌,第二个人重新排列后出牌,求最多得分。

很容易想到的二分图匹配,建图时写个函数比较一下牌的大小就够了。

#include<cstdio>#include<cstring>#include<algorithm>using namespace std;int mp[105][105];int to[555];bool vis[555];char s[10];char h[500];int n;int dfs(int k){    for(int i=0;i<n;i++)    {        if(!vis[i]&&mp[k][i])        {            vis[i]=1;            if(to[i]==-1||dfs(to[i]))            {                to[i]=k;                return 1;            }        }    }    return 0;}bool cmp(char *sa,char *sb){    if(h[sa[0]]==h[sb[0]]) return h[sa[1]]>h[sb[1]];    return h[sa[0]]>h[sb[0]];}char sa[105][5],sb[105][5];int main(){    h['H']=3;    h['S']=2;    h['D']=1;    h['C']=0;    for(int i='2';i<='9';i++) h[i]=i-'2';    h['T']=8;    h['J']=9;    h['Q']=10;    h['K']=11;    h['A']=12;    int cas;    scanf("%d",&cas);    while(cas--)    {        memset(mp,0,sizeof(mp));        memset(to,-1,sizeof(to));        scanf("%d",&n);        for(int i=0;i<n;i++)        {            scanf("%s",sa[i]);        }        for(int i=0;i<n;i++)        {            scanf("%s",sb[i]);        }        for(int i=0;i<n;i++)        {            for(int j=0;j<n;j++)            {                if(cmp(sb[j],sa[i])) mp[j][i]=1;            }        }        int ans=0;        for(int i=0;i<n;i++)        {            memset(vis,0,sizeof(vis));            ans+=dfs(i);        }        printf("%d\n",ans);    }    return 0;}

HDU 2119

行列分为二分图,若相交位置有1则连一条容量为INF的边,其他边容量为1,最小割就是消除所有1的解

#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<set>#include<map>#include<queue>#include<vector>#include<string>#define eps  1e-12#define INF   0x7fffffff#define maxn 22222using namespace std;int n,m;int en;int st,ed;//源点和汇点int dis[maxn] ;//dis[i],表示  到 原点  s 的 层数int que[9999999];struct edge{int to,c,next;};edge e[9999999];int head[maxn];void add(int a,int b,int c){e[en].to=b;e[en].c=c;e[en].next=head[a];head[a]=en++;e[en].to=a;e[en].c=0;e[en].next=head[b];head[b]=en++;}int bfs(){    memset(dis,-1,sizeof(dis));    dis[st]=0;    int front=0,rear=0;    que[rear++]=st;    while(front<rear)    {        int j=que[front++];        for(int k=head[j];k!=-1;k=e[k].next)        {            int i=e[k].to;if(dis[i]==-1&&e[k].c)            {                dis[i] = dis[j]+ 1 ;                que[rear++]=i;                if(i==ed) return true;            }        }    }    return false;}int dfs(int x,int mx){    int i,a;    if(x==ed) return mx ;int ret=0;    for(int k=head[x];k!=-1&&ret<mx;k=e[k].next)    {        if(e[k].c&&dis[e[k].to]==dis[x]+1)        {            int dd=dfs(e[k].to,min(e[k].c,mx-ret));            e[k].c-=dd;            e[k^1].c+=dd;            ret+=dd;        }    }    if(!ret) dis[x]=-1;    return ret;}void init(){    en=0;st=0;     //源    ed=n+m+10;     //汇memset(head,-1,sizeof(head));}void build(){    int x,y,z;    for(int i=1;i<=n;i++) add(st,i,1);    for(int j=1;j<=m;j++) add(j+n,ed,1);    for(int i=1;i<=n;i++)    {        for(int j=1;j<=m;j++)        {            scanf("%d",&x);            if(x==1) add(i,j+n,INF);        }    }}int dinic(){    int tmp=0;    int maxflow=0;    while(bfs())    {        while(tmp=dfs(st,INF)) maxflow+=tmp;    }    return maxflow;}int main(){    while(scanf("%d",&n)&&n)    {        scanf("%d",&m);        init();        build();        printf("%d\n",dinic());    }}


4 0