zoukankan      html  css  js  c++  java
  • SGU 326 Perspective(最大流)

    Description

    Breaking news! A Russian billionaire has bought a yet undisclosed NBA team. He's planning to invest huge effort and money into making that team the best. And in fact he's been very specific about the expected result: the first place. 
    Being his advisor, you need to determine whether it's possible for your team to finish first in its division or not. 
    More formally, the NBA regular season is organized as follows: all teams play some games, in each game one team wins and one team loses. Teams are grouped into divisions, some games are between the teams in the same division, and some are between the teams in different divisions. 
    Given the current score and the total number of remaining games for each team of your division, and the number of remaining games between each pair of teams in your division, determine if it's possible for your team to score at least as much wins as any other team in your division.

    Input

    The first line of input contains N (2 ≤ N ≤ 20) — the number of teams in your division. They are numbered from 1 to N, your team has number 1. 
    The second line of input contains N integers w1, w2,..., wN, where wi is the total number of games that ith team has won to the moment. 
    The third line of input contains N integers r1, r2,..., rN, where ri is the total number of remaining games for the ith team (including the games inside the division). 
    The next N lines contain N integers each. The jth integer in the ith line of those contains aij — the number of games remaining between teams i and j. It is always true that aij=a ji and aii=0, for all iai1+ ai2 +... + aiN  ri. 
    All the numbers in input are non-negative and don't exceed 10\,000.

    Output

    On the only line of output, print " 
    YES
    " (without quotes) if it's possible for the team 1 to score at least as much wins as any other team of its division, and " 
    NO
    " (without quotes) otherwise.

    题目大意:某小组有n支队伍要比赛,现在每支队伍已经赢了w[i]场,每支队伍还要比r[i]场,每场分同小组竞赛和不同小组竞赛,然后给一个矩阵(小组内竞赛),i行j列为队伍i与队伍j还要比多少场比赛,问队伍1有没有在小组内拿最高分(假设赢一场得一分)的可能性(可以跟其他队伍同分)

    思路:首先,队伍1要赢,最好是要1把所有比赛都赢了(包括小组内和小组外),然后其他小组的分都要尽量低,所以其他队伍都要输掉小组外的比赛。那么设小组1能赢max_score场。那么怎么分配其他比赛的获胜方呢?这里就要用到网络流建图。从源点到每支队伍间的比赛连一条边,容量为该竞赛的场数,然后该竞赛再向该比赛的两支队伍连一条容量为无穷大的边(你喜欢容量为场数也可以o(╯□╰)o)。然后,每支队伍(不包括1),连一条容量为max_score - w[i]的边到汇点(不能让这支队伍赢太多啊会超过1的o(╯□╰)o)。如果最大流等于小组内比赛数,那就是YES(分配了所有比赛的结果,还是没人能超过max_score,有可行解),否则输出NO。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <queue>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int INF = 0x7fff7fff;
     8 const int MAX = 25;
     9 const int MAXN = MAX * MAX;
    10 const int MAXE = 10 * MAXN;
    11 
    12 struct Dinic {
    13     int head[MAXN], cur[MAXN], dis[MAXN];
    14     int to[MAXE], next[MAXE], cap[MAXE], flow[MAXE];
    15     int n, st, ed, ecnt;
    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     bool bfs() {
    28         memset(dis, 0, sizeof(dis));
    29         queue<int> que; que.push(st);
    30         dis[st] = 1;
    31         while(!que.empty()) {
    32             int u = que.front(); que.pop();
    33             for(int p = head[u]; p; p = next[p]) {
    34                 int v = to[p];
    35                 if(!dis[v] && cap[p] > flow[p]) {
    36                     dis[v] = dis[u] + 1;
    37                     que.push(v);
    38                     if(v == ed) return true;
    39                 }
    40             }
    41         }
    42         return dis[ed];
    43     }
    44 
    45     int dfs(int u, int a) {
    46         if(u == ed || a == 0) return a;
    47         int outflow = 0, f;
    48         for(int &p = cur[u]; p; p = next[p]) {
    49             int v = to[p];
    50             if(dis[u] + 1 == dis[v] && (f = dfs(v, min(a, cap[p] - flow[p]))) > 0) {
    51                 flow[p] += f;
    52                 flow[p ^ 1] -= f;
    53                 outflow += f;
    54                 a -= f;
    55                 if(a == 0) break;
    56             }
    57         }
    58         return outflow;
    59     }
    60 
    61     int Maxflow(int ss, int tt, int nn) {
    62         st = ss; ed = tt; n = nn;
    63         int ans = 0;
    64         while(bfs()) {
    65             for(int i = 0; i <= n; ++i) cur[i] = head[i];
    66             ans += dfs(st, INF);
    67         }
    68         return ans;
    69     }
    70 } G;
    71 
    72 int r[MAX], w[MAX];
    73 int n;
    74 
    75 int main() {
    76     scanf("%d", &n);
    77     for(int i = 1; i <= n; ++i) scanf("%d", &w[i]);
    78     for(int i = 1; i <= n; ++i) scanf("%d", &r[i]);
    79     int max_score = w[1] + r[1], node_cnt = n, game_cnt = 0;
    80     for(int i = 2; i <= n; ++i)
    81         if(max_score < w[i]) {puts("NO"); return 0;}
    82     G.init();
    83     int ss = 1;
    84     for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) {
    85         int x; scanf("%d", &x);
    86         if(i == 1 || i >= j || x == 0) continue;
    87         game_cnt += x;
    88         G.add_edge(ss, ++node_cnt, x);
    89         G.add_edge(node_cnt, i, INF);
    90         G.add_edge(node_cnt, j, INF);
    91     }
    92     int tt = ++node_cnt;
    93     for(int i = 2; i <= n; ++i) G.add_edge(i, tt, max_score - w[i]);
    94     if(G.Maxflow(ss, tt, node_cnt) == game_cnt) puts("YES");
    95     else puts("NO");
    96 }
    View Code
  • 相关阅读:
    linux命令行
    mybatis中#{}和${}的区别
    @InitBinder的作用
    mui 实用封装销毁页面
    【SQLite】简单的基本使用步骤
    常用的一些操作方法
    【HttpWeb】Post和GET请求基本封装
    【接口验证】特性验证参数
    小谈单例模式
    vs下开端口直接调试iis
  • 原文地址:https://www.cnblogs.com/oyking/p/3237286.html
Copyright © 2011-2022 走看看