19_04_02校內訓練[deadline]

GreenDuck發表於2019-04-02

題意

給出一個二分圖,左邊為A集合,右邊為B集合,要求把A集合中每一個點染為黑白兩色中的一種,B集合中的顏色已定。染色後對於原本相鄰且顏色相同的點,建立新的二分圖,即得到了兩個新的二分圖,它們是獨立的。求出這兩個新的二分圖的最大匹配數的和的最小值。數均小於等於5000。


 

思考

這是簡化題意。由於暴力很難寫,考慮網路流。將B集合中的每一個點根據其顏色分為一類和二類點。對於A集合中的每一個點,拆成兩個點,兩點連1的單向邊,將所有相鄰的一類點連線左邊,另一類連向右邊,值為1。所有二類點連向匯點,源點連向所有一類點。最小割。

這樣,若割掉了某條邊,代表了將某個點相鄰的所有A集合中的點都染成了相同的顏色,並斷絕了其他點的後路。


 

程式碼

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1E5+5;
 4 const int inf=INT_MAX;
 5 int head[maxn*2],size=1,n,m,a[maxn],dfn[maxn],S,T,x,y,ans,k;
 6 struct edge{int to,next,w;}E[maxn*2];
 7 void add(int u,int v,int w)
 8 {
 9     E[++size].to=v;
10     E[size].next=head[u];
11     E[size].w=w;
12     head[u]=size;
13     
14     E[++size].to=u;
15     E[size].next=head[v];
16     E[size].w=0;
17     head[v]=size;
18 }
19 bool bfs()
20 {
21     queue<int>Q;
22     for(int i=0;i<=T;++i)dfn[i]=-1;
23     dfn[S]=0;
24     Q.push(S);
25     while(Q.size())
26     {
27         int u=Q.front();
28         Q.pop();
29         for(int i=head[u];i;i=E[i].next)
30         {
31             int v=E[i].to;
32             if(E[i].w==0||dfn[v]!=-1)continue;
33             dfn[v]=dfn[u]+1;
34             Q.push(v);
35         }
36     }
37     return dfn[T]!=-1;
38 }
39 int dinic(int u,int up)
40 {
41     if(u==T)return up;
42     int sum=0;
43     for(int i=head[u];i;i=E[i].next)
44     {
45         int v=E[i].to;
46         if(E[i].w==0||dfn[v]!=dfn[u]+1)continue;
47         int g=dinic(v,min(E[i].w,up-sum));
48         E[i].w-=g;
49         E[i^1].w+=g;
50         sum+=g;
51         if(g==0)dfn[v]=-1;
52         if(sum==up)break;
53     }
54     return sum;
55 }
56 int main()
57 {
58 //    freopen("deadline.in","r",stdin);
59 //    freopen("deadline.out","w",stdout);
60     ios::sync_with_stdio(false);
61     cin>>n>>m>>k;
62     for(int i=1;i<=n;++i)cin>>a[i];
63     for(int i=1;i<=k;++i)
64     {
65         cin>>x>>y;
66         if(a[x])add(x,y+n,inf);
67         else add(y+n+m,x,inf);
68     }
69     S=0;
70     T=n+m*2+1;
71     for(int i=1;i<=m;++i)add(i+n,i+n+m,1);
72     for(int i=1;i<=n;++i)
73         if(a[i])add(S,i,1);
74         else add(i,T,1);
75     while(bfs())ans+=dinic(S,inf);
76     cout<<ans<<endl;
77     return 0;
78 }
View Code

 

相關文章