ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

暑假集训Day6 B(带花树)

2022-07-12 23:31:42  阅读:152  来源: 互联网

标签:花树 匹配 fa Day6 MAX int 男生 集训


题目链接在这里: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 }

 

标签:花树,匹配,fa,Day6,MAX,int,男生,集训
来源: https://www.cnblogs.com/keximeiruguo/p/16472210.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有