URAL 1736 Chinese Hockey(网络最大流)

Description

Sergey and Denis closely followed the Chinese Football Championship, which has just come to an end. They supported the Katraps andKomolotiv teams, but, unfortunately, these teams tied for last place in the championship. Sergey was so disappointed that he suggested Denis that they change to hockey fans.
There are n teams competing in the Chinese Ice Hockey Championship. During the season, each team must play with each other team exactly one game. If a team wins in the regulation time, it gets 3 points and the losing team gets 0 points. If the regulation time is ended in a draw, then the overtime is played. The team that wins in the overtime gets 2 points and the team that loses gets 1 point. A game can't end in a draw in ice hockey.
Denis wants to determine which team he will support. In order to make the choice, he has found a table on the Web in which it is shown for each team how many points it scored in the last year's season. Sergey suspects that there is a mistake in this table because no all-play-all tournament could end with such results. Is Sergey right?

Input

The first line contains the integer n (2 ≤ n ≤ 200). The second line contains n space-separated non-negative integers; they are the scores of the teams in the previous championship. The scores are given in the non-increasing order. The sum of all the scores is 3n(n–1)/2. None of the teams scored more than 3(n–1) points.

Output

If Sergey is right and there is a mistake in the table, output “INCORRECT” in the only line. Otherwise, in the first line output “CORRECT” and in the following n(n–1)/2 lines output the results of the games. Each result must have the form “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 }
View Code

 

posted @ 2013-08-29 19:49  Oyking  阅读(542)  评论(0编辑  收藏  举报