BZOJ 1305 dance跳舞(最大流+二分答案)
题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1305
解题思路:
转自:https://blog.csdn.net/u012288458/article/details/50709571
二分答案
每个点拆成两个点x,x'
每个男生x向x'连一条容量为k的边
每个女生y'向y连一条容量为k的边
源点S向每个男生连一条容量为ans的边
每个女生向汇点T连一条容量为ans的边
对于男生x和女生y,
如果互相喜欢,则x向y连一条容量为1的边
如果不互相喜欢,则x’向y'连一条容量为1的边
若最大流为n*ans则可行,否则不可行
点数4n+2
边数(4n+n^2)*2
代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 #include<vector> 8 #define LL long long 9 #define pii pair<int,int> 10 #define pll pair<long long,long long> 11 #define rep(i,a,b) for(int i=a;i<=b;i++) 12 #define per(i,a,b) for(int i=a;i>=b;i--) 13 #define FAST_IO ios::sync_with_stdio(false);cin.tie(0); 14 #define bug cout<<"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"<<endl; 15 #define bugc(_) cout << (#_) << " = " << (_) << endl; 16 using namespace std; 17 const int N=5e2+5; 18 const int M=5e3+5; 19 const int INF=0x3f3f3f3f; 20 21 struct node{ 22 int to,next,flow; 23 }edge[M*2]; 24 25 int cnt,st,en,n,k; 26 int head[N],dep[N],like[N][N]; 27 28 void init(){ 29 cnt=2; 30 memset(head,0,sizeof(head)); 31 } 32 33 void link(int u,int v,int flow){ 34 edge[cnt]=node{v,head[u],flow}; 35 head[u]=cnt++; 36 edge[cnt]=node{u,head[v],0}; 37 head[v]=cnt++; 38 } 39 40 int bfs(){ 41 memset(dep,0,sizeof(dep)); 42 dep[st]=1; 43 queue<int>q; 44 q.push(st); 45 while(!q.empty()){ 46 int u=q.front(); 47 q.pop(); 48 for(int i=head[u];i;i=edge[i].next){ 49 node t=edge[i]; 50 if(t.flow&&!dep[t.to]){ 51 dep[t.to]=dep[u]+1; 52 q.push(t.to); 53 } 54 } 55 } 56 return dep[en]; 57 } 58 59 int dfs(int u,int fl){ 60 if(u==en) return fl; 61 for(int i=head[u];i;i=edge[i].next){ 62 node &t=edge[i]; 63 if(t.flow&&dep[u]+1==dep[t.to]){ 64 int x=dfs(t.to,min(t.flow,fl)); 65 if(x>0){ 66 t.flow-=x; 67 edge[i^1].flow+=x; 68 return x; 69 } 70 } 71 } 72 dep[u]=-2; 73 return 0; 74 } 75 76 int dinic(){ 77 int ans=0; 78 while(bfs()){ 79 while(int d=dfs(st,INF)){ 80 ans+=d; 81 } 82 } 83 return ans; 84 } 85 86 void build(int mid){ 87 init(); 88 for(int i=1;i<=n;i++){ 89 link(st,i,mid); 90 link(i,i+n,k); 91 link(i+2*n,en,mid); 92 link(i+3*n,i+2*n,k); 93 } 94 for(int i=1;i<=n;i++){ 95 for(int j=1;j<=n;j++){ 96 if(like[i][j]) 97 link(i,j+2*n,1); 98 else 99 link(i+n,j+3*n,1); 100 } 101 } 102 } 103 104 int main(){ 105 while(~scanf("%d%d",&n,&k)){ 106 for(int i=1;i<=n;i++){ 107 char tmp[100]; 108 scanf("%s",tmp+1); 109 for(int j=1;j<=n;j++){ 110 if(tmp[j]=='Y') 111 like[i][j]=1; 112 } 113 } 114 st=0,en=4*n+1; 115 int l=0,r=n,ans=-1; 116 while(l<=r){ 117 int mid=(l+r)/2; 118 build(mid); 119 int sum=dinic(); 120 if(sum>=n*mid){ 121 ans=mid; 122 l=mid+1; 123 } 124 else 125 r=mid-1; 126 } 127 printf("%d\n",ans); 128 } 129 return 0; 130 }