1. 程式人生 > >CQOI跳舞(網絡流+二分答案)

CQOI跳舞(網絡流+二分答案)

ons flow def 流量 fine bool 需要 depth namespace

題面見 https://www.luogu.org/problemnew/show/P3153

題意簡述:有n個男生,n個女生,每一首歌時兩位男女配對,然後同一對男女只能跳一場,一個人只會與不喜歡的人跳k場,求最大可以滿員跳幾場

這個題目看完可以猜測到這道題需要二分答案進行check()

然後就是建圖,首先在check的時候查看是否所有邊都流滿了,其次因為一對男女跳一場,所以建邊容量為1,然後男生和女生分別向原點和匯點連容量為mid的邊

最後就是如何實現與不喜歡的人跳k場,根據網絡流的常規操作,拆個點就很不錯,這個時候可以選擇這樣拆點把一個人拆成兩個分點,一個總點,一個總點代表有mid流量進來,兩個分點分別和喜歡還有不喜歡的人相連,總點向不喜歡的人連k容量,向喜歡的連mid容量,然後分點分別與喜歡和不喜歡相連

(我最後改成了把喜歡的分點合並到總點裏面去)

然後就是代碼了

// luogu-judger-enable-o2
#include<bits/stdc++.h>
#include<queue>
using namespace std;
#define INF 0x3f3f3f3f
inline int read(){
    int w=0,f=1;
    char ch=getchar();
    while(ch<0||ch>9){
        if(ch==-) f=-1;
        ch=getchar();
    }
    
while(ch>=0&&ch<=9){ w=(w<<3)+(w<<1)+ch-48; ch=getchar(); } return w*f; } int n,m,cur[100010],head[100010],cnt=1,depth[100010],maxflow,S,T; bool debug; const int p=1000; struct Edge{ int from,to,flow,dis,next; }edge[5000010]; queue<int> q; inline
void addedge(int u,int v,int w){ cnt++; edge[cnt].from=u; edge[cnt].to=v; edge[cnt].flow=w; edge[cnt].next=head[u]; head[u]=cnt; } inline void ins(int u,int v,int w){ addedge(u,v,w);addedge(v,u,0); } int mapp[110][110]; inline bool bfs(int st,int ed){ memset(depth,0,sizeof(depth));int i,j,k; for(i=0;i<=10010;i++) cur[i]=head[i]; depth[st]=1;q.push(st); while(!q.empty()){ int u=q.front();q.pop(); for(i=head[u];i;i=edge[i].next){ int v=edge[i].to; if(!depth[v]&&edge[i].flow){ q.push(v);depth[v]=depth[u]+1; } } } return depth[ed]; } inline int dfs(int u,int ed,int limit){ if(u==ed||!limit) return limit; int f,i,j,k;int flow=0; for(i=cur[u];i;i=edge[i].next){ cur[u]=i;int v=edge[i].to; if(depth[v]==depth[u]+1&&(f=dfs(v,ed,min(limit,edge[i].flow)))){ limit-=f;flow+=f; edge[i].flow-=f;edge[i^1].flow+=f; if(!limit) break; } } return flow; } inline void Dinic(){ while(bfs(S,T)){ //cout<<"fuck1"<<endl; maxflow+=dfs(S,T,INF); } } inline bool check(int a){ S=0;T=10000;int i,j,k;cnt=1;maxflow=0; memset(head,0,sizeof(head)); for(i=1;i<=n;i++){ ins(S,i,a); ins(i,i+n,m); ins(i+2*n,i+3*n,m); ins(i+3*n,T,a); } for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ if(mapp[i][j]) ins(i,j+3*n,1); else ins(i+n,j+2*n,1); } } Dinic(); //cout<<a<<" "<<maxflow<<endl; if(maxflow==a*n) return true; else return false; } int main(){ n=read();m=read();int i,j,k; for(i=1;i<=n;i++){ for(j=1;j<=n;j++){ char ch;cin>>ch; if(ch==Y) mapp[i][j]=1; else mapp[i][j]=0; } } int l=0,r=n+m;int ans; while(l<=r){ int mid=(l+r)>>1; //cout<<mid<<" "<<check(mid)<<endl; if(check(mid)) l=mid+1,ans=mid; else r=mid-1; } cout<<ans<<endl; return 0; }

CQOI跳舞(網絡流+二分答案)