標籤:
題目大意:有n支隊伍進行比賽,每支隊伍需要打的比賽次數相同,每場比賽恰好有一支隊伍勝,一支隊伍敗,給出每支隊伍目前勝的場數和敗的場數,以及每兩支隊伍還剩下的比賽場數,確定所有可能得冠軍的隊伍
解題思路:枚舉每支隊伍,然後讓該隊伍在接下來的所有比賽中都獲勝。
建圖的話,就比較簡單了,源點連向每場比賽,容量為比賽次數
每場比賽連向比賽隊伍,容量為比賽次數
接著每支隊伍連向匯點,容量為枚舉隊伍的總勝場-該隊伍的勝場
如果滿流,表示該隊伍可以得到冠軍
#include <cstdio>#include <cstring>#include <algorithm>#include <queue>using namespace std;#define M 1000010#define N 10010#define INF 0x3f3f3f3fstruct 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 30int 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;}
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
UVALive - 2531 The K-League(最大流+枚舉)