zoukankan      html  css  js  c++  java
  • [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;
    }
  • 相关阅读:
    wait/sleep/yield的区别
    54点提高PHP编程效率(转)
    ftp 使用
    转义 html 里特殊含义字符
    查看端口是否被占用
    webservice 获取调用者IP
    字符编码
    你有读过软件的协议或是网站的服务条款吗?
    使用TSQL的Rand函数生成随机数的艰苦历程
    几个.NET方面的问题——参考答案
  • 原文地址:https://www.cnblogs.com/wenci/p/10122656.html
Copyright © 2011-2022 走看看