zoukankan      html  css  js  c++  java
  • BZOJ 2597 剪刀石头布(最小费用最大流)(WC2007)

    Description

    在一些一对一游戏的比赛(如下棋、乒乓球和羽毛球的单打)中,我们经常会遇到A胜过BB胜过CC又胜过A的有趣情况,不妨形象的称之为剪刀石头布情况。有的时候,无聊的人们会津津乐道于统计有多少这样的剪刀石头布情况发生,即有多少对无序三元组(A, B, C),满足其中的一个人在比赛中赢了另一个人,另一个人赢了第三个人而第三个人又胜过了第一个人。注意这里无序的意思是说三元组中元素的顺序并不重要,将(A, B, C)(A, C, B)(B, A, C)(B, C, A)(C, A, B)(C, B, A)视为相同的情况。
    N个人参加一场这样的游戏的比赛,赛程规定任意两个人之间都要进行一场比赛:这样总共有场比赛。比赛已经进行了一部分,我们想知道在极端情况下,比赛结束后最多会发生多少剪刀石头布情况。即给出已经发生的比赛结果,而你可以任意安排剩下的比赛的结果,以得到尽量多的剪刀石头布情况。

    Input

    输入文件的第1行是一个整数N,表示参加比赛的人数。
    之后是一个NN列的数字矩阵:一共N行,每行N列,数字间用空格隔开。
    在第(i+1)行的第j列的数字如果是1,则表示i在已经发生的比赛中赢了j;该数字若是0,则表示在已经发生的比赛中i败于j;该数字是2,表示ij之间的比赛尚未发生。数字矩阵对角线上的数字,即第(i+1)行第i列的数字都是0,它们仅仅是占位符号,没有任何意义。
    输入文件保证合法,不会发生矛盾,当ij时,第(i+1)行第j列和第(j+1)行第i列的两个数字要么都是2,要么一个是0一个是1

    Output

    输出文件的第1行是一个整数,表示在你安排的比赛结果中,出现了多少剪刀石头布情况。
    输出文件的第2行开始有一个和输入文件中格式相同的NN列的数字矩阵。第(i+1)行第j个数字描述了ij之间的比赛结果,1表示i赢了j0表示i负于j,与输入矩阵不同的是,在这个矩阵中没有表示比赛尚未进行的数字2;对角线上的数字都是0。输出矩阵要保证合法,不能发生矛盾。
     
    PS:这题太牛叉了值得一做……
     
    代码(896MS):
      1 #include <cstdio>
      2 #include <cstring>
      3 #include <iostream>
      4 #include <algorithm>
      5 #include <queue>
      6 using namespace std;
      7 
      8 const int MAXN = 110;
      9 const int MAXV = MAXN * MAXN;
     10 const int MAXE = MAXN * MAXV;
     11 const int INF = 0x7f7f7f7f;
     12 
     13 struct ZWK_FLOW {
     14     int head[MAXV], dis[MAXV];
     15     int to[MAXE], next[MAXE], flow[MAXE], cost[MAXE];
     16     int n, ecnt, st, ed;
     17 
     18     void init() {
     19         memset(head, 0, sizeof(head));
     20         ecnt = 2;
     21     }
     22 
     23     void add_edge(int u, int v, int c, int w) {
     24         to[ecnt] = v; flow[ecnt] = c; cost[ecnt] = w; next[ecnt] = head[u]; head[u] = ecnt++;
     25         to[ecnt] = u; flow[ecnt] = 0; cost[ecnt] = -w; next[ecnt] = head[v]; head[v] = ecnt++;
     26         //printf("%d %d %d %d
    ", u, v, c, w);
     27     }
     28 
     29     void spfa() {
     30         for(int i = 1; i <= n; ++i) dis[i] = INF;
     31         priority_queue<pair<int, int> > que;
     32         dis[st] = 0; que.push(make_pair(0, st));
     33         while(!que.empty()) {
     34             int u = que.top().second, d = -que.top().first; que.pop();
     35             if(d != dis[u]) continue;
     36             for(int p = head[u]; p; p = next[p]) {
     37                 int &v = to[p];
     38                 if(flow[p] && dis[v] > d + cost[p]) {
     39                     dis[v] = d + cost[p];
     40                     que.push(make_pair(-dis[v], v));
     41                 }
     42             }
     43         }
     44         int t = dis[ed];
     45         for(int i = 1; i <= n; ++i) dis[i] = t - dis[i];
     46     }
     47 
     48     int minCost, maxFlow;
     49     bool vis[MAXV];
     50 
     51     int add_flow(int u, int aug) {
     52         if(u == ed) {
     53             maxFlow += aug;
     54             minCost += dis[st] * aug;
     55             return aug;
     56         }
     57         vis[u] = true;
     58         int now = aug;
     59         for(int p = head[u]; p; p = next[p]) {
     60             int &v = to[p];
     61             if(flow[p] && !vis[v] && dis[u] == dis[v] + cost[p]) {
     62                 int t = add_flow(v, min(now, flow[p]));
     63                 flow[p] -= t;
     64                 flow[p ^ 1] += t;
     65                 now -= t;
     66                 if(!now) break;
     67             }
     68         }
     69         return aug - now;
     70     }
     71 
     72     bool modify_label() {
     73         int d = INF;
     74         for(int u = 1; u <= n; ++u) if(vis[u]) {
     75             for(int p = head[u]; p; p = next[p]) {
     76                 int &v = to[p];
     77                 if(flow[p] && !vis[v]) d = min(d, dis[v] + cost[p] - dis[u]);
     78             }
     79         }
     80         if(d == INF) return false;
     81         for(int i = 1; i <= n; ++i) if(vis[i]) dis[i] += d;
     82         return true;
     83     }
     84 
     85     int min_cost_flow(int ss, int tt, int nn) {
     86         st = ss, ed = tt, n = nn;
     87         minCost = maxFlow = 0;
     88         spfa();
     89         while(true) {
     90             while(true) {
     91                 for(int i = 1; i <= n; ++i) vis[i] = false;
     92                 if(!add_flow(st, INF)) break;
     93             }
     94             if(!modify_label()) break;
     95         }
     96         return minCost;
     97     }
     98 } G;
     99 
    100 int n, m;
    101 int mat[MAXN][MAXN], ans[MAXN][MAXN];
    102 
    103 inline int encode(int i, int j) {
    104     if(i > j) swap(i, j);
    105     return i * n + j;
    106 }
    107 
    108 int main() {
    109     scanf("%d", &n);
    110     for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) scanf("%d", &mat[i][j]);
    111     m = n * n;
    112     int ss = n + m + 1, tt = ss + 1;
    113     G.init();
    114     int sum = n * (n - 1) * (n - 2) / 6;
    115     for(int i = 1; i <= n; ++i) {
    116         for(int j = 1, tmp = 1; j < n; ++j, tmp += 2) G.add_edge(ss, i, 1, tmp);
    117         for(int j = 1; j <= n; ++j) if(mat[i][j] != 0)
    118             ans[i][j] = G.ecnt, G.add_edge(i, encode(i, j), 1, 0);
    119     }
    120     for(int i = 1; i <= m; ++i) G.add_edge(i + n, tt, 1, 0);
    121     int x = G.min_cost_flow(ss, tt, tt);
    122     printf("%d
    ", sum - (x - n * (n - 1) / 2) / 2);
    123     for(int i = 1; i <= n; ++i) {
    124         for(int j = 1; j <= n; ++j) {
    125             if(j != 1) printf(" ");
    126             if(mat[i][j] != 2) printf("%d", mat[i][j]);
    127             else {
    128                 if(G.flow[ans[i][j]] == 0) printf("1");
    129                 else printf("0");
    130             }
    131         }
    132         puts("");
    133     }
    134 }
    View Code
  • 相关阅读:
    Codeforces Gym 100571A A. Cursed Query 离线
    codeforces Gym 100500 J. Bye Bye Russia
    codeforces Gym 100500H H. ICPC Quest 水题
    codeforces Gym 100500H A. Potion of Immortality 简单DP
    Codeforces Gym 100500F Problem F. Door Lock 二分
    codeforces Gym 100500C D.Hall of Fame 排序
    spring data jpa 创建方法名进行简单查询
    Spring集成JPA提示Not an managed type
    hibernate配置文件中的catalog属性
    SonarLint插件的安装与使用
  • 原文地址:https://www.cnblogs.com/oyking/p/3330462.html
Copyright © 2011-2022 走看看