您的位置:首页 > 产品设计 > UI/UE

uva 1306 The K-League (最大流)

2015-08-30 15:25 447 查看

uva 1306 The K-League

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

题目大意:有n支球队进行比赛,每只队伍需要打的比赛数目相同。每场比赛恰好一支队伍胜,另一支败。给出每支队伍目前胜的场数和败的场数,以及每两个队伍还剩下的比赛场数,确定所有可能的冠军的球队(获胜常数最多的的冠军,可以并列)。

解题思路:要分成n次来判断。对于当前队伍,使它在接下来的比赛中全部获胜,则它的获胜总场次为total。设置超级源点,连向每两队之间的比赛,容量为这两队之间还剩下的比赛场次。设置超级汇点,使所有队伍连向它,容量为total减去这支队伍已获胜的场次win[i]。然后每两队之间的比赛,连向这两只队伍,容量为INF。跑最大流,若连向超级源点的边能满流,则当前队伍有可能获得冠军。total - win[i]代表这支队伍在接下来的比赛中,胜利总场次不能超过当前队伍最多的胜利场次total。如果total - win[i] < 0或者连向超级源点的边没有满流,说明,其他队伍再怎么放水,这支队伍也得不到冠军。

[code]#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <queue>
#include <cctype>
using namespace std;

typedef long long ll;
const int PO = 30;
const int N = 1000;
const int M = 20000;
const int INF = 0x3f3f3f3f;
int n, F[PO][PO], s, t;
struct Node{
    int w, l;
}team[PO];

namespace IO {
    const static int maxn = 20 << 20;
    static char buf[maxn], *pbuf = buf, *End;
    void init() {
        int c = fread(buf, 1, maxn, stdin);
        End = buf + c;
    }
    int &readint() {
        static int ans;
        ans = 0;
        while (pbuf != End && !isdigit(*pbuf)) pbuf ++;
        while (pbuf != End && isdigit(*pbuf)) {
            ans = ans * 10 + *pbuf - '0';
            pbuf ++;
        }
        return ans;
    }
}

struct Edge{
    int from, to;
    int cap, flow; 
};

struct Dinic{
    vector<Edge> edges;
    vector<int> G[M];
    int vis
, d
;
    int cur[M];
    int ans;

    void init() {
        ans = 0;
        for (int i = 0; i < M; i++) G[i].clear();
        edges.clear();
    }

    void addEdge(int from, int to, int cap) {
        edges.push_back((Edge){from, to, cap, 0});
        edges.push_back((Edge){to, from, 0, 0});
        int m = edges.size();
        G[from].push_back(m - 2);
        G[to].push_back(m - 1);
    } 

    int BFS() {
        memset(vis, 0, sizeof(vis));
        queue<int> Q;
        Q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while (!Q.empty()) {
            int u = Q.front(); Q.pop(); 
            for (int i = 0; i < G[u].size(); i++) {
                Edge &e = edges[G[u][i]];   
                if (!vis[e.to] && e.cap > e.flow) {
                    vis[e.to] = 1;  
                    d[e.to] = d[u] + 1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }

    int DFS(int u, int a) {
        if (u == t || a == 0) return a;
        int flow = 0, f; 
        for (int &i = cur[u]; i < G[u].size(); i++) {
            Edge &e = edges[G[u][i]];
            if (d[u] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow))) > 0) {
                e.flow += f;    
                edges[G[u][i]^1].flow -= f;
                flow += f;
                a -= f;
                if (a == 0) break;
            }
        }
        return flow;
    }

    int dinic() {
        while (BFS()) {
            memset(cur, 0, sizeof(cur));
            ans += DFS(s, INF);
        }   
        return ans;
    }
}din;

void input() {
    n = IO::readint();
    s = 0, t = n * (n + 1) + 2;
    for (int i = 1; i <= n; i++) {
        team[i].w = IO::readint();
        team[i].l = IO::readint();
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            F[i][j] = IO::readint();
        }   
    }
}

int getTotal(int x) {
    int sum = team[x].w;
    for (int i = 1; i <= n; i++) {
        sum += F[x][i]; 
    }
    return sum;
} 

void solve() {
    for (int i = 1; i <= n; i++) {
        din.addEdge(i, t, 0);   
    }
    int cnt = 1, rec = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = i + 1; j <= n; j++) {
            din.addEdge(s, cnt + n, F[i][j]);   
            rec += F[i][j];
            din.addEdge(cnt + n, i, INF);
            din.addEdge(cnt + n, j, INF);
            cnt++;
        }   
    }
    int flag = 0;
    for (int i = 1; i <= n; i++) {
        int tot = getTotal(i), cap;
        for (int j = 0; j < din.edges.size(); j++) din.edges[j].flow = 0;
        for (int j = 0; j < 2 * n; j += 2) {
            cap = tot - team[(j / 2) + 1].w;
            if (cap < 0) {
                cap = -1;
                break;
            }
            din.edges[j].cap = cap;
        }
        if (cap == -1) continue;
        din.ans = 0;
        if (din.dinic() == rec) {
            if (flag) printf(" ");
            printf("%d", i);
            flag = 1;
        }
    }puts("");
}

int main() {
    IO::init();
    int T;
    T = IO::readint();
    while (T--) {
        din.init();
        input();        
        solve();
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: