zoukankan      html  css  js  c++  java
  • 【bzoj1532】[POI2005]Kos-Dicing 【网络流】【二分】

    题意:有n个人,m场两个人之间的比赛。问赢得最多的那个人最少赢多少场。
    题解:首先二分答案。然后建图跑网络流。
    s>1
    >1
    >tmid
    然后跑最大流,判断是否等于比赛总数即可。
    代码:

    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int N=20005,M=100005;
    int n,m,l,r,mid,cnt,s,t,u[N],v[N],head[N],dep[N],to[M],nxt[M],dd[M];
    queue<int> q;
    void adde(int u,int v,int d){
        to[++cnt]=v;
        nxt[cnt]=head[u];
        dd[cnt]=d;
        head[u]=cnt;
        to[++cnt]=u;
        nxt[cnt]=head[v];
        dd[cnt]=d;
        head[v]=cnt;
    }
    bool bfs(){
        memset(dep,0,sizeof(dep));
        dep[s]=1;
        while(!q.empty()){
            q.pop();
        }
        q.push(s);
        while(!q.empty()){
            int u=q.front(),v;
            q.pop();
            for(int i=head[u];i;i=nxt[i]){
                v=to[i];
                if(dd[i]&&!dep[v]){
                    dep[v]=dep[u]+1;
                    q.push(v);
                }
            }
        }
        return dep[t];
    }
    int dfs(int u,int f){
        if(u==t||!f){
            return f;
        }
        int tmp,res=0,v;
        for(int i=head[u];i&&f;i=nxt[i]){
            v=to[i];
            if(dd[i]&&dep[v]==dep[u]+1&&(tmp=dfs(v,min(f,dd[i])))){
                dd[i]-=tmp;
                dd[i^1]+=tmp;
                f-=tmp;
                res+=tmp;
            }
        }
        if(!res){
            dep[u]=0;
        }
        return res;
    }
    int maxflow(){
        int res=0;
        while(bfs()){
            res+=dfs(s,0x7fffffff);
        }
        return res;
    }
    bool check(){
        cnt=1,s=0,t=n+m+1;
        memset(head,0,sizeof(head));
        for(int i=1;i<=m;i++){
            adde(s,i,1);
            adde(i,u[i]+m,1);
            adde(i,v[i]+m,1);
        }
        for(int i=1;i<=n;i++){
            adde(i+m,t,mid);
        }
        return maxflow()==m;
    }
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++){
            scanf("%d%d",&u[i],&v[i]);
        }
        l=0,r=m+1;
        while(l<r){
            mid=(l+r)/2;
            if(check()){
                r=mid;
            }else{
                l=mid+1;
            }
        }
        printf("%d
    ",l);
        return 0;
    }
  • 相关阅读:
    Java职业生涯规划
    Java类加载器总结
    Java字节流与字符流的区别
    Java堆和栈的区别
    详解Java类的生命周期
    Java编程常见问题汇总
    Java总结输入流输出流
    Java NIO:浅析I/O模型
    perl 处理文件路径的一些模块
    Delphi第三方控件安装卸载指南
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476859.html
Copyright © 2011-2022 走看看