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

题目大意:有n支队伍进行比赛,每支队伍需要打的比赛次数相同,每场比赛恰好有一支队伍胜,一支队伍败,给出每支队伍目前胜的场数和败的场数,以及每两支队伍还剩下的比赛场数,确定所有可能得冠军的队伍

解题思路:枚举每支队伍,然后让该队伍在接下来的所有比赛中都获胜。

建图的话,就比较简单了,源点连向每场比赛,容量为比赛次数

每场比赛连向比赛队伍,容量为比赛次数

接着每支队伍连向汇点,容量为枚举队伍的总胜场-该队伍的胜场

如果满流,表示该队伍可以得到冠军

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;

#define M 1000010
#define N 10010
#define INF 0x3f3f3f3f
struct Edge{
    int u, v, cap, flow, next;
}E[M];

struct Dinic{
    int head[N], d[N];
    int tot, sink, source;

    void init() {
        memset(head, -1, sizeof(head));
        tot = 0;
    }

    inline void AddEdge(int u, int v, int cap) {
        E[tot].u = u; E[tot].v = v; E[tot].cap = cap; E[tot].flow = 0; E[tot].next = head[u]; head[u] = tot++;
        u = u ^ v; v = u ^ v; u = u ^ v;
        E[tot].u = u; E[tot].v = v; E[tot].cap = 0; E[tot].flow = 0; E[tot].next = head[u]; head[u] = tot++;
    }

    inline bool bfs(int s) {
        int u, v;
        memset(d, 0, sizeof(d));
        queue<int> Q;
        Q.push(s);
        d[s] = 1;
        while (!Q.empty()) {
            u = Q.front(); Q.pop();
            if (u == sink) return true;
            for (int i = head[u]; ~i; i = E[i].next) {
                v = E[i].v;
                if (!d[v] && E[i].cap - E[i].flow > 0) {
                    d[v] = d[u] + 1;
                    Q.push(v);
                }
            }
        }
        return false;
    }

    int dfs(int x, int a) {
        if (x == sink || a == 0)
            return a;
        int f, flow = 0;
        for (int i = head[x]; ~i; i = E[i].next) {
            int v = E[i].v;
            if (d[v] == d[x] + 1 && E[i].cap - E[i].flow > 0) {
                f = dfs(v, min(a, E[i].cap - E[i].flow));
                E[i].flow += f;
                E[i^1].flow -= f;
                flow += f;
                a -= f;
                if (!a) break;
            }
        }
        if (flow == 0) d[x] = 0;
        return flow;
    }

    int Maxflow(int source, int sink) {
        int flow = 0;
        this->sink = sink;
        while (bfs(source)) flow += dfs(source, INF);
        return flow;
    }
};

Dinic dinic;
#define maxn 30
int n;
int win[maxn], fight[maxn][maxn], all, Max;
void init() {
    scanf("%d", &n);
    all = 0;
    Max = -INF;
    int t;

    for (int i = 1; i <= n; i++) {
        scanf("%d%d", &win[i], &t);
        Max = max(Max, win[i]);
        if (i == 1)
            all += win[i] + t;
    }

    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) {
            scanf("%d", &fight[i][j]);
            if (i == 1)
                all += fight[i][j];
        }
}

void solve() {
    bool flag = false;
    int total, source = 0, sink =  N - 1, cnt;
    for (int i = 1; i <= n; i++) {
        total = win[i];
        for (int j = 1; j <= n; j++)
            total += fight[i][j];

        if (total < Max)
            continue;
        cnt = n + 1;
        dinic.init();
        int Sum = 0;
        for (int j = 1; j <= n; j++) {
            if (j != i) dinic.AddEdge(j, sink, total - win[j]);
            for (int k = j + 1; k <= n; k++) {
                if (j == i || k == i)
                    continue;
                dinic.AddEdge(source, cnt, fight[j][k]);
                Sum += fight[j][k];
                dinic.AddEdge(cnt, j, fight[j][k]);
                dinic.AddEdge(cnt++, k, fight[j][k]);
            }
        }
        int MaxFlow = dinic.Maxflow(source, sink);
        if (MaxFlow == Sum) {
            if (flag)
                printf(" ");
            flag = true;
            printf("%d", i);
        }
    }
    printf("\n");
}

int main() {
    int test;
    scanf("%d", &test);
    while (test--) {
        init();
        solve();
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-07 05:16:42

UVALive - 2531 The K-League(最大流+枚举)的相关文章

UVALive - 3972 March of the Penguins(最大流+枚举)

题目大意:有n个冰块,每块冰块能承受mi只企鹅从上面跳走 初始时每个冰块上有ai只企鹅,每只企鹅跳跃的最远距离为d,要求所有的企鹅在同一片冰块上集合,问哪些冰块满足要求 解题思路:这题和HDU - 2732 Leapin' Lizards 类似,具体的就不讲了,枚举+最大流就可以了 #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <c

【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

星际转移问题(最大流 枚举)

使用并查集判断有无解,若有解枚举天数若最大流等于人数则可行. //http://www.cnblogs.com/IMGavin/ #include <iostream> #include <stdio.h> #include <cstdlib> #include <cstring> #include <queue> #include <vector> #include <map> #include <stack>

1189. [HNOI2007]紧急疏散EVACUATE【最大流+枚举或二分】

Description 发生了火警,所有人员需要紧急疏散!假设每个房间是一个N M的矩形区域.每个格子如果是'.',那么表示这是一 块空地:如果是'X',那么表示这是一面墙,如果是'D',那么表示这是一扇门,人们可以从这儿撤出房间.已知门 一定在房间的边界上,并且边界上不会有空地.最初,每块空地上都有一个人,在疏散的时候,每一秒钟每个人都 可以向上下左右四个方向移动一格,当然他也可以站着不动.疏散开始后,每块空地上就没有人数限制了(也就是 说每块空地可以同时站无数个人).但是,由于门很窄,每一秒

UVALive - 2957 Bring Them There(最大流 图论建模)

题目大意:有n个星球,你的任务是用最短的时间把k个超级计算机从S星球运送到T星球.每个超级计算机需要一艘飞船来运输,行星之间有m条双向隧道,每条隧道需要一天时间来通过,且不能有两艘飞船同时使用同一条隧道,隧道不会连接两个相同的行星,且每一对行星之间最多只有一条隧道 解题思路:按照大白书上的思路是拆点 比如运送的时间为T,那么就把每个点u拆成T + 1个,分别为u0, u1 - uT,分别对应的是第i天的u星球 对于所给的每条边(u,v),假设是第i天,就连边ui –>vi+1和vi–>ui+1

UVALive - 2197 Paint the Roads(费用流)

题目大意:有n个点,m条边,你的任务是选择其中的一些边,使得每条被选择的边组成一些没有公共边的回路,且每个城市恰好在其中的k个回路上,被选择的边的总权值要求最小 解题思路:k个回路,每个城市都有,表示每个城市的入度和出度都是k,所以以此建边 源点连向每个城市,容量为k,费用0 每个城市连向汇点,容量为k,费用0 边连接两个城市,容量为1,费用为权值 跑最小费用最大流 #include <cstdio> #include <cstring> #include <algorith

POJ 2699 The Maximum Number of Strong Kings (最大流+枚举)

http://poj.org/problem?id=2699 题意: 一场联赛可以表示成一个完全图,点表示参赛选手,任意两点u, v之间有且仅有一条有向边(u, v)或( v, u),表示u打败v或v打败u.一个选手的得分等于被他打败的选手总数.一个选手被称为“strong king”当且仅当他打败了所有比他分高的选手.分数最高的选手也是strong king.现在给出某场联赛所有选手的得分序列,由低到高,问合理安排每场比赛的结果后最多能有几个strong king.已知选手总数不超过10个.

【 UVALive - 5095】Transportation(费用流)

Description There are N cities, and M directed roads connecting them. Now you want to transport K units ofgoods from city 1 to city N. There are many robbers on the road, so you must be very careful. Themore goods you carry, the more dangerous it is.

UVALive 2474 Balloons in a Box(枚举)

https://vjudge.net/contest/277824#problem/A 尤其是模拟题,三思而后敲!!! 纠错了好久,主要还是没有处理好:单点若还未放气球,其他气球可以膨胀越过它(即可以无视这个点):如果选到一个点,它已经在某一气球半径内了,则置r=0. 还参考了一些其他测试数据 1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<vector> 5 #i