Description
Input
Output
i ? j
”, where
i
and
j
are the numbers of the teams that played the game and
?
can be
<
,
<=
,
>=
, or
>
, which means that the first team lost in the regulation time, lost in the overtime, won in the overtime, and won in the regulation time, respectively. The teams are numbered from 1 to
n
in the order in which they are given in the input.
题目大意:有n支队,每两队之间进行一场比赛,胜者得3分,败者0分。若为加时赛胜利者2分,败者1分。现在给所有队伍比完赛的得分,问有没有可能构造出这个得分,并输出得到这个得分的每一场比赛的结果。
思路:构建网络流。新开源点S汇点T,从源点到每一场比赛连一条容量为3的边,从每一场比赛到这场比赛的双方连一条边,容量为无穷大(大于等于3就行),从每一支队到汇点连一条边,容量为这个队伍的最终得分。若满流,则有解。每场比赛到比赛双方的边的流量,就是这场比赛某方的得分。
代码(31MS):
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 8 const int MAXN = 210 * 210; 9 const int MAXE = MAXN * 5; 10 const int INF = 0x3fff3fff; 11 12 struct SAP { 13 int head[MAXN], pre[MAXN], dis[MAXN], cur[MAXN], gap[MAXN]; 14 int next[MAXE], to[MAXE], cap[MAXE], flow[MAXE]; 15 int n, ecnt, st, ed; 16 17 void init() { 18 memset(head, 0, sizeof(head)); 19 ecnt = 2; 20 } 21 22 void add_edge(int u, int v, int c) { 23 to[ecnt] = v; cap[ecnt] = c; flow[ecnt] = 0; next[ecnt] = head[u]; head[u] = ecnt++; 24 to[ecnt] = u; cap[ecnt] = 0; flow[ecnt] = 0; next[ecnt] = head[v]; head[v] = ecnt++; 25 } 26 27 void bfs() { 28 memset(dis, 0x3f, sizeof(dis)); 29 queue<int> que; que.push(ed); 30 dis[ed] = 0; 31 while(!que.empty()) { 32 int u = que.front(); que.pop(); 33 ++gap[dis[u]]; 34 for(int p = head[u]; p; p = next[p]) { 35 int &v = to[p]; 36 if(cap[p ^ 1] && dis[v] > n) { 37 dis[v] = dis[u] + 1; 38 que.push(v); 39 } 40 } 41 } 42 } 43 44 int Max_flow(int ss, int tt, int nn) { 45 st = ss, ed = tt, n = nn; 46 int ans = 0, minFlow = INF, u; 47 for(int i = 0; i <= n; ++i) { 48 cur[i] = head[i]; 49 gap[i] = 0; 50 } 51 bfs(); 52 u = pre[st] = st; 53 while(dis[st] < n) { 54 bool flag = false; 55 for(int &p = cur[u]; p; p = next[p]) { 56 int &v = to[p]; 57 if(cap[p] > flow[p] && dis[u] == dis[v] + 1) { 58 flag = true; 59 minFlow = min(minFlow, cap[p] - flow[p]); 60 pre[v] = u; 61 u = v; 62 if(u == ed) { 63 ans += minFlow; 64 while(u != st) { 65 u = pre[u]; 66 flow[cur[u]] += minFlow; 67 flow[cur[u] ^ 1] -= minFlow; 68 } 69 minFlow = INF; 70 } 71 break; 72 } 73 } 74 if(flag) continue; 75 int minDis = n - 1; 76 for(int p = head[u]; p; p = next[p]) { 77 int &v = to[p]; 78 if(cap[p] > flow[p] && dis[v] < minDis) { 79 minDis = dis[v]; 80 cur[u] = p; 81 } 82 } 83 if(--gap[dis[u]] == 0) break; 84 ++gap[dis[u] = minDis + 1]; 85 u = pre[u]; 86 } 87 return ans; 88 } 89 } G; 90 91 int n, a[210]; 92 int game_id[210][210]; 93 94 int main() { 95 scanf("%d", &n); 96 for(int i = 1; i <= n; ++i) scanf("%d", &a[i]); 97 G.init(); 98 int ss = n + n * (n - 1) / 2 + 1, tt = ss + 1; 99 int cnt = n + 1; 100 for(int i = 1; i <= n; ++i) { 101 G.add_edge(i, tt, a[i]); 102 for(int j = i + 1; j <= n; ++j) { 103 game_id[i][j] = G.ecnt; 104 G.add_edge(cnt, i, 3); 105 G.add_edge(cnt, j, 3); 106 G.add_edge(ss, cnt, 3); 107 ++cnt; 108 } 109 } 110 if(G.Max_flow(ss, tt, tt) != 3 * n * (n - 1) / 2) puts("INCORRECT"); 111 else { 112 puts("CORRECT"); 113 for(int i = 1; i <= n; ++i) { 114 for(int j = i + 1; j <= n; ++j) { 115 switch(G.flow[game_id[i][j]]) { 116 case 0:printf("%d < %d\n", i, j);break; 117 case 1:printf("%d <= %d\n", i, j);break; 118 case 2:printf("%d >= %d\n", i, j);break; 119 case 3:printf("%d > %d\n", i, j);break; 120 } 121 } 122 } 123 } 124 }