Java教程

暑假集训Day6 B(带花树)

本文主要是介绍暑假集训Day6 B(带花树),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

题目链接在这里:B (codeforces.com)

答案要求两女夹一男的匹配数,很显然不能用一般的二分图匹配去做,但是这既然是个匹配问题,题目是人出出来的,很显然还是需要转化成我们平时做的那种匹配。所以我们考虑把男生拆开拆成两个点,然后跑一般图匹配。最后拿匹配数减去男生人数就是结果。这就是一个带花树问题,我们知道,带花树匹配一定是间隔匹配,所以如果是答案要求的一对匹配,我们带花树会跑出两个(因为我们将男生拆成两个点看),而对于不合法的匹配(同一个男生自己跟自己匹配),那么最后减去男生人数的时候也把这个减掉了,所以结果是正确的。

后面遇到了匹配问题还是要想经典的二分图匹配和带花树,因为万变不离其宗,所有的匹配问题都是以这两个为出发点的。

  1 #include "bits/stdc++.h"
  2 using namespace std;
  3 const int MAX=505;
  4 int n,m,tot,cnt,fa[MAX];
  5 int head[MAX],nxt[MAX*MAX],adj[MAX*MAX];
  6 int vis[MAX],id[MAX],ff[MAX],mat[MAX],ans;
  7 int q[2000005],st,ed;
  8 char s[MAX];
  9 inline int getfather(int x){return (fa[x]==x?x:fa[x]=getfather(fa[x]));}
 10 inline int read(){
 11     int an=0,x=1;char c=getchar();
 12     while (c<'0' || c>'9') {if (c=='-') x=-1;c=getchar();}
 13     while (c>='0' && c<='9') {an=an*10+c-'0';c=getchar();}
 14     return an*x;
 15 }
 16 inline void addedge(int u,int v){
 17     tot++;
 18     adj[tot]=v;
 19     nxt[tot]=head[u];
 20     head[u]=tot;
 21 }
 22 inline int lca(int x,int y){
 23     cnt++;
 24     while (vis[x]!=cnt){
 25         if (x){
 26             x=getfather(x);
 27             if (vis[x]==cnt) return x;
 28             vis[x]=cnt;
 29             if (mat[x]!=0)
 30                 x=getfather(ff[mat[x]]);
 31             else x=0;
 32         }
 33         swap(x,y);
 34     }
 35     return x;
 36 }
 37 inline void work(int x,int y,int k){
 38     int z;
 39     while (getfather(x)!=k){
 40         ff[x]=y;
 41         z=mat[x];
 42         if (id[z]==1){
 43             id[z]=0;
 44             q[++ed]=z;
 45         }
 46         if (getfather(z)==z) fa[z]=k;
 47         if (getfather(x)==x) fa[x]=k;
 48         y=z;x=ff[y];
 49     }
 50 }
 51 inline bool bfs(int x){
 52     int i,j,u,v;
 53     int la,no,t,z;
 54     for (i=1;i<=n;i++) fa[i]=i;
 55     memset(id,-1,sizeof(id));
 56     st=ed=0;
 57     q[++ed]=x;id[x]=0;
 58     while (st<ed){
 59         u=q[++st];
 60         for (i=head[u];i;i=nxt[i]){
 61             v=adj[i];
 62             if (id[v]==-1){
 63                 ff[v]=u,id[v]=1;
 64                 if (!mat[v]){
 65                     no=v;
 66                     while (no){
 67                         t=ff[no];
 68                         la=mat[t];
 69                         mat[t]=no;mat[no]=t;
 70                         no=la;
 71                     }
 72                     return true;
 73                 }
 74                 id[mat[v]]=0;
 75                 q[++ed]=mat[v];
 76             }
 77             else if (id[v]==0 && getfather(u)!=getfather(v)){
 78                 z=lca(u,v);
 79                 work(u,v,z);work(v,u,z);
 80             }
 81         }
 82     }
 83     return false;
 84 }
 85 int main(){
 86     freopen ("b.in","r",stdin);freopen ("b.out","w",stdout);
 87     int i,j,u,v,cas;
 88     scanf("%d",&cas);
 89     while (cas--){
 90         n=read(),m=read();
 91 //        scanf("%d %d",&n,&m);
 92         ans=tot=cnt=0;
 93         memset(head,0,sizeof(head));
 94         memset(ff,0,sizeof(ff));
 95         memset(vis,0,sizeof(vis));
 96         memset(mat,0,sizeof(mat));
 97         memset(fa,0,sizeof(fa));
 98         int now=n;
 99         for (i=1;i<=n;i++){
100             scanf("\n%s",s+1);
101             addedge(i,i+n);
102             addedge(i+n,i);
103             for (j=1;j<=m;j++)
104                 if (s[j]=='1'){
105                     addedge(i,2*n+j);
106                     addedge(2*n+j,i);
107                     addedge(i+n,2*n+j);
108                     addedge(2*n+j,i+n);
109                 }
110         }
111         n=2*n+m;
112         for (i=1;i<=n;i++)
113             if (!mat[i] && bfs(i))
114                 ans++;
115         printf("%d\n",ans-now);
116     }
117     return 0;
118 }

 

这篇关于暑假集训Day6 B(带花树)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!