• 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
  • 相关阅读:
    sqlMetal用法和例子 自定义DBML
    List使用Foreach 修改集合时,会报错的解决方案 (Error: Collection was modified; enumeration operation may not execute. )
    HTTP 和 SOAP 标头 来传递用户名密码 验证webservice用户认证
    static与线程安全 -摘自网络
    Win7 64位 安装E10后 打不开的解决方案 -摘自网络
    JQuery Dialog 禁用X按钮关闭对话框,-摘自网络
    MVC client validation after PartialView loaded via Ajax MVC3中 弹出 Dialog时候 提交的时候 使用 Jquery 不验证 form表单 的解决办法
    授权给adfs读取ad 在ad服务器上运行
    Configuring Active Directory Federation Services 2.0 (配置 adfs 2.0) -摘自网络
    MyEclipse10下创建web项目并发布到Tomcat
  • 原文地址:https://www.cnblogs.com/oyking/p/3330462.html
Copyright © 2020-2023  润新知