• 洛谷P1264


    比较好的网络流题。

    Description

    给出每个队目前的胜场,已经还未进行的比赛情况,问有哪些队伍可能会成为全场胜场最多的队伍。

    Solution

    这个建图有最小权闭合子图的感觉。

    首先,考虑什么时候可以胜场最多,显然是如果一个队伍剩下的所有比赛都赢了,然后获胜的场次是全场最多时,他才有可能是全场胜场最多的。

    所以我们就可以遍历每个队伍,依次让他们取得所有的胜利,然后判断一下他们是否可以成为胜场最多的队伍。

    因为每两个队伍进行一场比赛,所以我们可以将比赛和队伍分别作为点来建图。

    具体方法如下,对于每个队伍:

    • 首先统计当前队伍的最大胜场(已胜和可能胜的);

    • 源点向对于每组比赛连容量为比赛场次的边;

    • 每组比赛向参加的两支队伍分别连容量无穷大的边;

    • 每支队伍向汇点连容量为自己的当前胜场数与当前的最大胜场差值的边。

    然后跑出的每组最大流,如果等于当前还未进行的总场次,那么说明当前这支队伍可能成为全场胜场最多的队伍。

    然后有几个地方:

    1. 如果统计完一个队伍的胜场之后仍比另一个队伍的已胜场次少,那么就不用跑网络流了;

    2. 如果当前边的容量是 0 的话可以不用建这条边,否则会出奇奇怪怪的错误,比如超时等等;

    3. 总场次如果在输入中处理,记得除以二;

    4. 每次循环记得初始化。

    #include<cmath>
    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define rr register 
    #define maxn 5010
    #define INF 0x3f3f3f3f
    //#define int long long
    using namespace std;
    
    int n,tot=1,s,t,cnt,all;
    int a[maxn][maxn],id[maxn][maxn];
    int Dis[maxn],head[maxn],cur[maxn];
    struct node{int win,defeat;}b[maxn];
    struct edge{int fr,to,dis,nxt;}e[maxn*maxn];
    
    inline int read(){
        rr int s=0,w=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-') w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')s=(s<<1)+(s<<3)+ch-'0',ch=getchar();
        return s*w;
    }
    
    void add(int fr,int to,int dis){
        e[++tot]=(edge){fr,to,dis,head[fr]};head[fr]=tot;
        e[++tot]=(edge){to,fr,0,head[to]};head[to]=tot;
    }
    
    bool bfs(){
        memset(Dis,-1,sizeof Dis);
        queue<int> q;q.push(s);
        Dis[s]=0;cur[s]=head[s];
        while(!q.empty()){
            int u=q.front();q.pop();
            for(int i=head[u];i;i=e[i].nxt){
                int to=e[i].to;
                if(e[i].dis&&Dis[to]==-1){
                    q.push(to);
                    Dis[to]=Dis[u]+1;
                    cur[to]=head[to];
                    if(to==t) return true;
                }
            }
        }
        return false;
    }
    
    int dfs(int u,int limit){
        if(u==t) return limit;int flow=0;
        for(int i=cur[u];i&&flow<limit;i=e[i].nxt){
            int to=e[i].to;cur[u]=i;
            if(e[i].dis&&Dis[to]==Dis[u]+1){
                int f=dfs(to,min(e[i].dis,limit-flow));
                if(!f)Dis[to]=-1;e[i].dis-=f;e[i^1].dis+=f;
                flow+=f;
            }
        }
        return flow;
    }
    
    int dinic(){
        int Maxflow=0,flow=0;
        while(bfs())
            while(flow=dfs(s,INF))
                Maxflow+=flow;
        return Maxflow;
    }
    
    void clear(){
        tot=1;
        memset(cur,0,sizeof cur);
        memset(head,0,sizeof head);
    }
    
    int main(){
        n=read();s=n*(n+3);t=s+1;
        for(rr int i=1;i<=n;i++)
            b[i].win=read(),b[i].defeat=read();
        for(rr int i=1;i<=n;i++)for(rr int j=1;j<=n;j++)
            all+=(a[i][j]=read()),id[i][j]=++cnt;
        for(rr int i=1,tMxs;i<=n;i++){
            tMxs=b[i].win;bool flag=0;
            for(rr int j=1;j<=n;j++) tMxs+=a[i][j];
            for(rr int j=1;j<=n;j++) if(tMxs<b[j].win){flag=1;break;}
            if(flag) continue;
            for(rr int j=1;j<=n;j++){
                for(rr int k=j+1;k<=n;k++){
                    if(a[k][j]) add(s,id[j][k]+n,a[k][j]);
                    add(id[j][k]+n,j,INF),add(id[j][k]+n,k,INF);
                }   
                if(tMxs-b[j].win>=0) add(j,t,tMxs-b[j].win);
            }
            int ans=dinic();
            if(ans==all/2) printf("%d ",i);clear();
        }
        return 0;
    }
    
  • 相关阅读:
    git rror: RPC失败
    linux加载模块报错:could not insert module xxx.ko: Unknown symbol in module
    Ubuntu 20.04 添加当前用户 Root 权限
    C程序编译过程
    静态代码块和非静态代码块
    java反射
    ==和equal的区别
    solr中配置域
    Solr的简介以及安装
    Spring Data Redis 小demo
  • 原文地址:https://www.cnblogs.com/KnightL/p/14829263.html
Copyright © 2020-2023  润新知