[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;
}
原文地址:https://www.cnblogs.com/wenci/p/10122656.html