【BZOJ 2744】【HEOI2012】朋友圈
题目链接:
题解:
对于A国,我们发现,最大团一定不大于2。对于B国,发现同奇偶性点之间都有边,不同奇偶性之间可能有边,也就是说对于B国是一个二分图最大团,也就是求B国补图的二分图最大独立集。然后,我们枚举使用A国的人员,将其与B国连接的点做一个补图,跑跑匈牙利即可。
【注】大视野上测试点和题面不一样啊!MMP没有t读入,只有一组数据,日哦!!
代码:
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 5 using namespace std; 6 7 inline int read(){ 8 int s=0,k=1;char ch=getchar(); 9 while(ch<'0'|ch>'9') ch=='-'?k=-1:0,ch=getchar(); 10 while(ch>47&ch<='9') s=s*10+(ch^48),ch=getchar(); 11 return s*k; 12 } 13 14 const int N=3e3+3; 15 16 int A,B,M; 17 18 struct edges{ 19 int v;edges *last; 20 }edge[N*N],*head[N<<2];int cnt; 21 22 inline void push(int u,int v){ 23 edge[++cnt]=(edges){v,head[u]};head[u]=edge+cnt; 24 } 25 26 struct Country{ 27 int sgl[N<<2],cpl[N<<2]; 28 int cnt_sgl,cnt_cpl; 29 int val[N<<2],re[N<<2]; 30 inline void add(int x,int pos){ 31 if(x&1){ 32 sgl[++cnt_sgl]=pos; 33 val[pos]=x;re[pos]=cnt_sgl; 34 }else{ 35 cpl[++cnt_cpl]=pos; 36 val[pos]=x;re[pos]=cnt_cpl; 37 } 38 } 39 inline void clear(){ 40 cnt_sgl=cnt_cpl=0; 41 } 42 }a,b; 43 44 int f[N<<2];bool vis[N<<2]; 45 46 inline bool find(int x){ 47 48 for(edges *i=head[x];i;i=i->last){ 49 if(!vis[i->v]){ 50 vis[i->v]=true; 51 if(f[i->v]==-1||find(f[i->v])){ 52 f[i->v]=x; 53 return true; 54 } 55 } 56 } 57 return false; 58 } 59 60 int v[500][N<<2],size[N<<2],tt[N<<2]; 61 62 inline void build(){ 63 for(int i=1;i<=b.cnt_sgl;i++) 64 if(tt[b.sgl[i]]==2){ 65 for(int j=1;j<=b.cnt_cpl;j++) 66 if(tt[b.cpl[j]]==2){ 67 int x=b.val[b.sgl[i]]|b.val[b.cpl[j]]; 68 int t(0); 69 while(x) t+=x&1,x>>=1; 70 if((~t)&1) 71 push(i,j); 72 } 73 } 74 } 75 76 inline int solve(){ 77 memset(f,-1,sizeof(f)); 78 int ret=0; 79 for(int i=1;i<=B;i++) 80 ret+=tt[i]==2; 81 for(int i=1;i<=b.cnt_sgl;i++){ 82 if(tt[b.sgl[i]]==2){ 83 memset(vis,0,sizeof(vis)); 84 if(find(i)) 85 ret--; 86 } 87 } 88 return ret; 89 } 90 91 inline void clear(){ 92 memset(head,0,sizeof(head)); 93 cnt=0; 94 } 95 96 97 int main(){ 98 // freopen(".in","r",stdin); 99 // freopen(".out","w",stdout); 100 clear(); 101 a.clear();b.clear(); 102 memset(v,0,sizeof(v)); 103 memset(size,0,sizeof(size)); 104 A=read(),B=read(),M=read(); 105 for(int i=1;i<=A;i++) a.add(read(),i); 106 for(int i=1;i<=B;i++) b.add(read(),i); 107 for(int i=1,u,vv;i<=M;i++){ 108 u=read(),vv=read(); 109 v[u][++size[u]]=vv; 110 } 111 for(int i=1;i<=B;i++) 112 tt[i]=2; 113 build(); 114 int ans=(a.cnt_sgl>0)+(a.cnt_cpl>0); 115 ans=max(ans,solve()); 116 memset(tt,0,sizeof(tt)); 117 for(int i=1;i<=a.cnt_sgl;i++){ 118 for(int j=1;j<=size[a.sgl[i]];j++) 119 tt[v[a.sgl[i]][j]]=2; 120 clear(); 121 build(); 122 ans=max(ans,solve()+1); 123 for(int j=1;j<=size[a.sgl[i]];j++) 124 tt[v[a.sgl[i]][j]]=0; 125 } 126 for(int j=1;j<=a.cnt_cpl;j++){ 127 for(int k=1;k<=size[a.cpl[j]];k++) 128 tt[v[a.cpl[j]][k]]=2; 129 clear(); 130 build(); 131 ans=max(ans,solve()+1); 132 for(int k=1;k<=size[a.cpl[j]];k++) 133 tt[v[a.cpl[j]][k]]=0; 134 } 135 for(int i=1;i<=a.cnt_sgl;i++){ 136 for(int j=1;j<=size[a.sgl[i]];j++) 137 tt[v[a.sgl[i]][j]]++; 138 for(int j=1;j<=a.cnt_cpl;j++){ 139 for(int k=1;k<=size[a.cpl[j]];k++) 140 tt[v[a.cpl[j]][k]]++; 141 clear(); 142 build(); 143 ans=max(ans,solve()+2); 144 for(int k=1;k<=size[a.cpl[j]];k++) 145 tt[v[a.cpl[j]][k]]--; 146 } 147 for(int j=1;j<=size[a.sgl[i]];j++) 148 tt[v[a.sgl[i]][j]]--; 149 } 150 printf("%d\n",ans); 151 152 }
没有什么不可能。