解题:HEOI 2012 朋友圈

题面

因为$A$中只有奇偶性不同的人才能做朋友,所以A中只可能出0/1/2个人,分类讨论

然后$B$中求最大团,转成补图后正好是个二分图(不然就不用做了),求最大点独立集=总点数-最大匹配

我洛谷上交的时候建边的时候制杖了,成了$O(n^2m^2)$建边,还好数据水跑不满+网络流跑得快900ms救回来了,估计BZOJ肯定gg了,正确的做法是直接对B全部建然后走边的时候判一下

  1 #include<cstdio>
  2 #include<vector>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 const int N=100005,M=4000005,inf=1e9;
  7 int p[N],from[M],noww[M],goal[M],flw[M],flow[M];
  8 int a[N],b[N],pp[N],ch[N],dep[N],que[N];
  9 int T,n,m,s,t,fr,bk,q,t1,t2,cnt,ans;
 10 vector<int> ve[N];
 11 vector<int> ::iterator it; 
 12 bool Odd(int x){return x&1;}
 13 bool Even(int x){return !(x&1);}
 14 int Bitcount(int x)
 15 {
 16     int ret=0;
 17     while(x)
 18         ret++,x-=x&-x;
 19     return ret;
 20 }
 21 void Link(int f,int t,int v)
 22 {
 23     noww[++cnt]=p[f],p[f]=cnt,from[cnt]=f;
 24     goal[cnt]=t,flw[cnt]=flow[cnt]=v;
 25     noww[++cnt]=p[t],p[t]=cnt,from[cnt]=t;
 26     goal[cnt]=f,flw[cnt]=flow[cnt]=0;
 27 }
 28 bool Layering(int st,int ed)
 29 {
 30     for(int i=1;i<=ed;i++) 
 31         pp[i]=p[i],dep[i]=-1;
 32     dep[st]=0,que[fr=bk=0]=st;
 33     while(fr<=bk)
 34     {
 35         int tn=que[fr++];
 36         for(int i=pp[tn];i;i=noww[i])
 37             if(ch[from[i]]&&ch[goal[i]])
 38                 if(dep[goal[i]]==-1&&flow[i])
 39                     dep[goal[i]]=dep[tn]+1,que[++bk]=goal[i];
 40     }
 41     return ~dep[ed];
 42 }
 43 int Augmenting(int nd,int ed,int mn)
 44 {
 45     if(nd==ed||!mn) return mn;
 46     int tmp=0,tep=0;
 47     for(int i=pp[nd];i;i=noww[i])
 48         if(ch[from[i]]&&ch[goal[i]])
 49         {
 50             pp[nd]=i;
 51             if(dep[goal[i]]==dep[nd]+1)
 52                 if(tep=Augmenting(goal[i],ed,min(mn,flow[i])))
 53                 {
 54                     flow[i]-=tep,mn-=tep;
 55                     flow[i^1]+=tep,tmp+=tep;
 56                     if(!mn) break;
 57                 }
 58         }
 59     return tmp;
 60 }
 61 int Dinic_Maxflow(int st,int ed)
 62 {
 63     int ret=0;
 64     while(Layering(st,ed))
 65         ret+=Augmenting(st,ed,inf);
 66     return ret;
 67 }
 68 int main()
 69 {
 70     register int i,j,k;
 71     scanf("%d",&T);
 72     while(T--)
 73     {
 74         scanf("%d%d%d",&n,&m,&q),ans=0;
 75         for(i=1;i<=n;i++) ve[i].clear();
 76         for(i=1;i<=n;i++) scanf("%d",&a[i]);
 77         for(i=1;i<=m;i++) scanf("%d",&b[i]);
 78         for(i=1;i<=q;i++) 
 79             scanf("%d%d",&t1,&t2),ve[t1].push_back(t2);
 80         cnt=1,s=m+1,t=s+1;
 81         for(i=1;i<=m+2;i++) ch[i]=1,p[i]=0;
 82         for(i=1;i<=m;i++)
 83             for(j=i+1;j<=m;j++)
 84                 if(Odd(b[i]^b[j])&&Even(Bitcount(b[i]|b[j])))
 85                     Odd(b[i])?Link(i,j,1):Link(j,i,1);
 86         for(i=1;i<=m;i++) 
 87             Odd(b[i])?Link(s,i,1):Link(i,t,1);
 88         ans=max(ans,m-Dinic_Maxflow(s,t));
 89         for(i=1;i<=n;i++)
 90         {
 91             int tmp=0;
 92             for(j=1;j<=m;j++) ch[j]=0;
 93             for(j=2;j<=cnt;j++) flow[j]=flw[j];
 94             for(it=ve[i].begin();it!=ve[i].end();it++) tmp++,ch[*it]=1;
 95             ans=max(ans,tmp-Dinic_Maxflow(s,t)+1);
 96         }
 97         for(i=1;i<=n;i++)
 98             for(k=i+1;k<=n;k++)
 99                 if(Odd(a[i]^a[k]))
100                 {
101                     int tmp=0;
102                     for(j=1;j<=m;j++) ch[j]=0;
103                     for(j=2;j<=cnt;j++) flow[j]=flw[j];
104                     for(it=ve[i].begin();it!=ve[i].end();it++) ch[*it]++;
105                     for(it=ve[k].begin();it!=ve[k].end();it++) ch[*it]++;
106                     for(j=1;j<=m;j++) ch[j]==2?tmp++,ch[j]=1:ch[j]=0;
107                     ans=max(ans,tmp-Dinic_Maxflow(s,t)+2);
108                 }
109         printf("%d
",ans);
110     }
111     return 0;
112 }
View Code
原文地址:https://www.cnblogs.com/ydnhaha/p/10284006.html