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 }

 

posted @ 2018-10-30 22:23  Yeader  阅读(196)  评论(0编辑  收藏  举报