UVA 1306 The K-League (最大流)

来源:互联网 发布:dll编程书籍 编辑:程序博客网 时间:2024/04/30 01:40
题意:有n支球队进行比赛,每只队伍需要打的比赛数目相同。每场比赛恰好一支队伍胜,另一支败。给出每支队伍目前胜的场数和败的场数,以及每两个队伍还剩下的比赛场数,确定所有可能的冠军的球队(获胜常数最多的的冠军,可以并列)。


思路:让i在所有队伍中取胜,设总共赢的场数为sum,那么剩下的队伍j最多只能赢sum - w[j],建立附加源点汇点,u,v之间有比赛的话,建立一个比赛节点,比赛节点连向u,v,容量为比赛场数,源点指向比赛节点,容量也为比赛场数,u,v再指向汇点容量为他们最多还能胜利的场数,如果最大流等于还剩下的场数,那么i队伍是可能胜利的


#include<cstdio>#include<cstring>#include<vector>#include<queue>#include<algorithm>const int INF = 1e8;const int maxn = 500;using namespace std;struct P {    int to, cap, rev;    P(int t, int c, int r) : to(t), cap(c), rev(r) {}};int n, m, num, p[30];int s, t, T, w[30];int now[30][30], ans[30];int lv[maxn], it[maxn];vector<P> G[maxn];void add(int from, int to, int cap) {    G[from].push_back(P(to, cap, G[to].size()));    G[to].push_back(P(from, 0, G[from].size() - 1));}bool bfs() {    memset(lv, -1, sizeof(lv));    lv[s] = 0;    queue<int> q; q.push(s);    while(!q.empty()) {        int u = q.front(); q.pop();        for(int i = 0; i < G[u].size(); i++) {            P &e = G[u][i];            if(lv[e.to] != -1 || !e.cap) continue;            lv[e.to] = lv[u] + 1;            q.push(e.to);        }    }    return lv[t] != -1;}int dfs(int u, int f) {    if(u == t) return f;    for(int &i = it[u]; i < G[u].size(); i++) {        P &e = G[u][i];        if(lv[e.to] <= lv[u] || !e.cap) continue;        int c = dfs(e.to, min(f, e.cap));        if(!c) continue;        G[u][i].cap -= c;        G[e.to][e.rev].cap += c;        return c;    }    return 0;}int dinic() {    int f = 0, fl;    while(1) {        if(!bfs()) return f;        memset(it, 0, sizeof(it));        while((fl = dfs(s, INF)) > 0) f += fl;    }}bool win(int id, int tal) {    int st = 1, sum = 0;    for(int i = 0; i < maxn; i++)        G[i].clear();    for(int i = 1; i <= n; i++) {        if(i == id) continue;        for(int j = i + 1; j <= n; j++) {            if(!now[i][j] || j == id) continue;            sum += now[i][j];            add(s, st, now[i][j]);            add(st, i + m, now[i][j]);            add(st, j + m, now[i][j]);            st++;        }        if(w[i] > tal) return false;        add(i + m, t, tal - w[i]);    }    int maxf = dinic();    if(maxf == sum) return true;    return false;}int main() {    scanf("%d", &T);    while(T--) {        scanf("%d", &n);        for(int i = 1; i <= n; i++) {            scanf("%d %d", &w[i], &m);            m = num = 0;        }        for(int i = 1; i <= n; i++) {            for(int j = 1; j <= n; j++) {                scanf("%d", &now[i][j]);                if(now[i][j]) m++;            }        }        m /= 2;        s = 0; t = n + m + 1;        for(int i = 1; i <= n; i++) {            int sum = w[i];            for(int j = 1; j <= n; j++) sum += now[i][j];            if(win(i, sum)) ans[num++] = i;        }        for(int i = 0; i < num; i++)            printf("%d%c", ans[i], i < num - 1 ? ' ' : '\n');    }    return 0;}


0 0