[POI2005]KOS-Dicing (最大流+二分)lg3425
Posted wenci
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[POI2005]KOS-Dicing (最大流+二分)lg3425相关的知识,希望对你有一定的参考价值。
题面https://www.luogu.org/problemnew/show/P3425
题面说赢的最多的人最少赢几场,肯定是向二分的方向思考
建立源点向每一场比赛连容量为1的边,从每场比赛向参赛两个人各连一条容量为1的边,表示一场比赛有一个人赢
二分一个最多的人赢的场数,从每个人向汇点连容量为mid的边,若最大流等于场数,说明符合题意,可以减小最多的人赢的场数,反之缩小
因为要输出方案,可以记录下满足条件的最小答案,然后以这个答案再跑一次,从比赛流向个人的边如果容量为0(也就是在增广时被流过了)说明他赢了这场比赛
#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,cnt=-1,head[100010],cur[100010],depth[100010],S,T,u[100010],v[100010],ans,x[100010],y[100010]; const int p=10000; bool vis[100010]; struct Edge{ int from,to,next,flow; }edge[1000010]; 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); } queue<int> q; inline bool bfs(int st,int ed){ memset(depth,0,sizeof(depth)); int u,v,i,j,k;q.push(st);depth[st]=1; for(i=S;i<=T;i++)cur[i]=head[i]; while(!q.empty()){ u=q.front();q.pop(); for(i=head[u];i!=-1;i=edge[i].next){ v=edge[i].to; if(!depth[v]&&edge[i].flow){ depth[v]=depth[u]+1;q.push(v); } } } return depth[ed]; } inline int dfs(int u,int ed,int limit){ if(!limit||u==ed) return limit; int v,i,j,k;int flow=0,f; for(i=cur[u];i!=-1;i=edge[i].next){ v=edge[i].to;cur[u]=i; 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)){ ans+=dfs(S,T,INF); } } inline bool check(int mid){ cnt=-1;memset(head,-1,sizeof(head)); int i,j,k; for(i=1;i<=m;i++){ ins(S,i,1); ins(i,x[i]+p,1); ins(i,y[i]+p,1); } for(i=1;i<=n;i++){ ins(i+p,T,mid); } ans=0;Dinic(); return ans==m; } int main(){ n=read();m=read();int i,j,k;int ans1; memset(head,-1,sizeof(head));S=0;T=99999; for(i=1;i<=m;i++){ x[i]=read();y[i]=read(); } int l=0,r=m+1; while(l<=r){ int mid=(l+r)>>1; if(check(mid)) r=mid-1,ans1=mid; else l=mid+1; } cout<<ans1<<endl; check(ans1); for(int u=1;u<=m;u++){ for(i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].to;v-=p;if(v<1 or edge[i].flow) continue; if(v==x[u]) vis[u]=true; } } for(i=1;i<=m;i++){ printf("%d ",vis[i]); } return 0; }
以上是关于[POI2005]KOS-Dicing (最大流+二分)lg3425的主要内容,如果未能解决你的问题,请参考以下文章
[bzoj1532] [POI2005]Kos-Dicing
[Luogu3425][POI2005]KOS-Dicing
bzoj 2095 [Poi2010]Bridges 判断欧拉维护,最大流+二分
BZOJ1537: [POI2005]Aut- The Bus
bzoj1733[Usaco2005 feb]Secret Milking Machine 神秘的挤奶机 二分+网络流最大流