POJ1336 The K-League[最大流 公平分配问题]

The K-League

Time Limit: 1000MS   Memory Limit: 10000K
Total Submissions: 715   Accepted: 251

Description

Supporters for the professional soccer clubs participating in the K-League, formerly the Korea Professional Soccer League, hold orderly and organized cheering, as did the Red Devils, the official supporters for the Korean national soccer team during the 2002 Korea-Japan World Cup. After many games of this season have been played, the supporters may wonder whether the team S they are backing can still win the championship. In other words, can winners be assigned for the remaining games so that no team ends with more victories than S?(Two or more teams can win the championship jointly.)

You are given the current number of wins and defeats, wi and di, for every team i, 1<=i<=n, and the remaining number, ai,j, of games to be played between every pair of teams i and j, 1<=i,j<=n, where n is the number of teams. The teams are numbered 1,2,...,n. You are to find all teams that have a possibility of winning the championship. Every team has to play the same number games during the season. For simplicity, we assume that there are no draws, that is, every game has a winner and a loser.

Input

The input consists of T test cases. The number of test cases (T) is given in the first line of the input file. Each test case consists of three lines: the first line has an integer n, 1<=n<=25, that represents the number of teams in the test case; the second line contains 2n nonnegative integers w1,d1,w2,d2... each at most 100, where wi and di are the current numbers of wins and defeats for team i, respectively; the third line contains n2 nonnegative integers a1,1,a1,2,... each at most 10, where ai,j is the remaining number of games to be played between teams i and j . For all i and j, ai,j=aj,i. If i=j, then ai,j=0. The integers given in a line are delimited by one or more spaces.

Output

Print exactly one line for each test case. The line should contain all teams that have a possibility of winning the championship, in an increasing order of team numbers.

Sample Input

3
3
2 0 1 1 0 2
0 2 2
2 0 2
2 2 0
3
4 0 2 2 0 4
0 1 1
1 0 1
1 1 0
4
0 3 3 1 1 3 3 0
0 0 0 2
0 0 1 0
0 1 0 0
2 0 0 0

Sample Output

1 2 3
1 2
2 4

Source

Taejon 2002


公平分配模型

判断队伍i能否获胜,让i的所有比赛都获胜,其他就是把比赛的胜利分配给队伍,是他们的获胜次数<=i的获胜次数

每场比赛(i,j)一个点,s到(i,j)连容量为c[i][j]的边,(i,j)到i和j分别连INF

除i外节点j到t连 i获胜次数-win[j] 的边

注意 i获胜次数-win[j] 的边<0一定不行

//
//  main.cpp
//  poj1336
//
//  Created by Candy on 26/11/2016.
//  Copyright © 2016 Candy. All rights reserved.
//

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1005,INF=1e9;
int read(){
    char c=getchar();int x=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1; c=getchar();}
    while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘; c=getchar();}
    return x*f;
}
int T,n,num,sum,win[N],los[N],s,t,c[N][N];
struct edge{
    int v,ne,c,f;
}e[N<<1];
int cnt,h[N];
inline void ins(int u,int v,int c){//printf("ins %d %d %d\n",u,v,c);
    cnt++;
    e[cnt].v=v;e[cnt].c=c;e[cnt].f=0;e[cnt].ne=h[u];h[u]=cnt;
    cnt++;
    e[cnt].v=u;e[cnt].c=0;e[cnt].f=0;e[cnt].ne=h[v];h[v]=cnt;
}
int tot;
bool build(int x){//printf("build %d\n",tot);
    cnt=0;
    memset(h,0,sizeof(h));
    for(int i=1;i<=n;i++) if(i!=x){
        for(int j=i+1;j<=n;j++) if(j!=x){
            int id=(i-1)*n+j;
            ins(s,id,c[i][j]);
            ins(id,num+i,INF);
            ins(id,num+j,INF);
        }
        ins(num+i,t,tot-win[i]);
        if(tot-win[i]<0) return false;
    }
    return true;
}
int cur[N];
int vis[N],d[N],q[N],head,tail;
bool bfs(){
    memset(vis,0,sizeof(vis));
    memset(d,0,sizeof(d));
    head=tail=1;
    q[tail++]=s;d[s]=0;vis[s]=1;
    while(head!=tail){
        int u=q[head++];
        for(int i=h[u];i;i=e[i].ne){
            int v=e[i].v;
            if(!vis[v]&&e[i].c>e[i].f){
                vis[v]=1;d[v]=d[u]+1;
                q[tail++]=v;
                if(v==t) return 1;
            }
        }
    }
    return 0;
}
int dfs(int u,int a){
    if(u==t||a==0) return a;
    int flow=0,f;
    for(int &i=cur[u];i;i=e[i].ne){
        int v=e[i].v;
        if(d[v]==d[u]+1&&(f=dfs(v,min(a,e[i].c-e[i].f)))>0){
            flow+=f;
            e[i].f+=f;
            e[((i-1)^1)+1].f-=f;
            a-=f;
            if(a==0) break;
        }
    }
    return flow;
}
int dinic(){
    int flow=0;
    while(bfs()){
        for(int i=s;i<=t;i++) cur[i]=h[i];
        flow+=dfs(s,INF);
    }
    return flow;
}
int main(int argc, const char * argv[]) {
    T=read();
    while(T--){
        n=read();s=0;t=n*n+n+1;num=n*n;sum=0;
        for(int i=1;i<=n;i++) win[i]=read(),los[i]=read();
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++) c[i][j]=read(),sum+=j>i?c[i][j]:0;

        for(int i=1;i<=n;i++){//printf("sol %d\n",i);
            tot=win[i];
            for(int j=1;j<=n;j++) tot+=c[i][j];
            if(!build(i)) continue;
            int tmp=dinic();//printf("dinic %d  sum %d  %d\n",tmp,sum,sum-tot+win[i]);
            if(tmp==sum-tot+win[i]) printf("%d ",i);
        }
        puts("");
    }

    return 0;
}
时间: 2024-07-29 23:33:25

POJ1336 The K-League[最大流 公平分配问题]的相关文章

【Uvalive 2531】 The K-League (最大流-类似公平分配问题)

[题意] 有n个队伍进行比赛,每场比赛,恰好有一支队伍取胜.一支队伍败.每个队伍需要打的比赛场数相同,给你每个队伍目前已经赢得场数和输得场数,再给你一个矩阵,第 i 行第 j 列 表示队伍 i 和队伍 j 还需要打的比赛数,问你哪些队伍有可能获得冠军(胜场最多的即为冠军,可以并列). InputThe input consists of T test cases. The number of test cases (T) is given in the first line of the inp

uvalive 3231 Fair Share 公平分配问题 二分+最大流 右边最多流量的结点流量尽量少。

/** 题目: uvalive 3231 Fair Share 公平分配问题 链接:https://vjudge.net/problem/UVALive-3231 题意:有m个任务,n个处理器,每个任务有两个候选处理器,只要其中一个运行,该任务就能执行. 不同任务的两个候选处理器,至少有一个不同. 求任务数最多的那个处理器所分配的任务数尽量少. 思路:二分+最大流 左边是任务,s->u,cap = 1. 如果任务u和u的候选处理器v,u->v, cap = 1. 右边是处理器,二分mi.所有处

hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙

/** 题目:hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4106 题意:给你n个数,每连续m个数,最多选k个数,问可以选的数的权值和最大多少. 思路:可以转化为区间k覆盖问题.区间k覆盖问题是每个点最多被k个区间覆盖.本题是每个区间最多选k个点. 刚好相反.我的做法有点不同其他博客那种做法.当然本质一样. 我这里的i就是原来n个数的下标,现在作为图中该数的节点编号

UVALive-2531 The K-League (最大流建模+枚举)

题目大意:有n支足球队,已知每支球队的已胜场数和任意两支球队之间还需要的比赛场数a[i][j],求最终可能夺冠的所有球队. 题目分析:枚举所有的球队,对于球队 i 让它在接下来的比赛中全部获胜,如果这样球队 i 还不能夺冠,那么 i 不是要找的,否则,就是答案.这道题可以建立公平分配问题的模型.将任意两个之间还有比赛的球队视作一个节点X(由u和v构成,即a[u][v]>0),则对于X有两个选择:u获胜或v获胜.这样的一个X相当于一个“任务”,对于每个任务X有两个“处理器”(u和v)供选择.建图如

BZOJ 2324 营救皮卡丘(最小费用最大流)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2324 题意:n+1个城市(0到n).初始时K个 人都在0城市.城市之间有距离.要求(1)遍历完n个城市(有一个人遍历了某个城市就算这个城市被遍历了):(2)遍历i城市前必须遍历完前i-1个城 市,并且在遍历前i-1个城市时不能经过大于等于i的城市.在满足(1)(2)的前提下使得K个人走的总距离最小. 思路:我们先看在实际情况下可以怎么走. (1)某个人遍历完某个城市后停在那里,以后不再

WFQ加权公平队列(每个队列的计算原则与权重比关系)加权效果后转发取证

WFQ加权公平队列(每个队列的计算原则与权重比关系)                                   及加权效果取证 加权公平队列(Weighted FairQueuing),它不允许用户使用MQC语句来手工完成对流量的分类,因为WFQ的分类是自动完成的,它基于每一种不同的流(flow)来分类,然后将不同的flow送入不同的队列.在实施WFQ的队列调度时主要是为了两个目标:一.为不同的数据流提供公平的服务:二.它可以为具备高优先级(较高IP优先级或者DSCP值)的数据提供更多

poj 2526 Minimum Cost【最小费用最大流】

题目链接:http://poj.org/problem?id=2516 题意: n个店主 m个供应商 k种货物 给你店主对k种货物的需求及供货商k种货物的囤货量及K种运输费用. 解法:k次费用流,分别求每种货物的费用.源点到供应点建边,店主到汇点建边,费用均为0,容量为1.然后供应点到店主建边,费用为矩阵,容量无穷大即可. 代码: /* POJ 2195 Going Home 邻接矩阵形式最小费用最大流 */ #include<stdio.h> #include<iostream>

POJ 2516 Minimum Cost 【费用流】

建模比较难想.. #include<iostream> #include<deque> #include<vector> #include<cstring> #include<cmath> #define INF 2e9 using namespace std; int T,ans; struct edge{ int v,cap,reverse,cost; }; vector<int> edges[1005];//邻接表 vector

多源多汇费用流——poj2516

网络流的题好难..感觉有点遭不住了 这题用矩阵存图,然后把k个物品,每个物品都求一次费用流 /* 多源多汇的费用流 其实是k个费用流 */ #include<bits/stdc++.h> using namespace std; #define inf 0x3f3f3f3f #define maxn 205 struct Edge{int to,nxt,w,c;}e[maxn<<2]; int head[maxn],tot,n,m,s,t; void init(){} void a