BZOJ2597 [Wc2007]剪刀石头布

什么鬼。。。冬令营题目不看题解能做?

(看了题解也不会2333)

其中有一部还是可以仔细思考一下的,就是对于费用流,如果每条边边满足:cost = a * flow2,如何做?

我们可以拆边,新边上,每条边流量为1,费用为a * (x2 - (x - 1)2)(就是费用为a * (12 - 02), a * (22 - 12)...)

拆边的思想还是很广泛的,恩...!

  1 /**************************************************************
  2     Problem: 2597
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:11144 ms
  7     Memory:10756 kb
  8 ****************************************************************/
  9
 10 #include <cstdio>
 11 #include <cstring>
 12 #include <algorithm>
 13
 14 using namespace std;
 15 const int Num = 105;
 16 const int N = Num * Num;
 17 const int M = 500005;
 18 const int inf = (int) 1e9;
 19
 20 struct edges {
 21     int next, to, f, cost;
 22     edges() {}
 23     edges(int _n, int _t, int _f, int _c) : next(_n), to(_t), f(_f), cost(_c) {}
 24 } e[M];
 25
 26 int tot = 1, first[N];
 27 int n, m, S, T;
 28 int in[Num], d[N], q[N], g[N];
 29 int sum[M];
 30 bool v[N];
 31
 32 inline int read() {
 33     int x = 0;
 34     char ch = getchar();
 35     while (ch < ‘0‘ || ‘9‘ < ch)
 36         ch = getchar();
 37     while (‘0‘ <= ch && ch <= ‘9‘) {
 38         x = x * 10 + ch - ‘0‘;
 39         ch = getchar();
 40     }
 41     return x;
 42 }
 43
 44 inline void Add_Edges(int x, int y, int f, int c) {
 45     e[++tot] = edges(first[x], y, f, c), first[x] = tot;
 46     e[++tot] = edges(first[y], x, 0, -c), first[y] = tot;
 47 }
 48
 49 inline int calc() {
 50     int flow = inf, x;
 51     for (x = g[T]; x; x = g[e[x ^ 1].to])
 52         flow = min(flow, e[x].f);
 53     for (x = g[T]; x; x = g[e[x ^ 1].to])
 54         e[x].f -= flow, e[x ^ 1].f += flow;
 55     return flow;
 56 }
 57
 58 bool spfa() {
 59     int x, y, l, r;
 60     for (x = 1; x <= T; ++x)
 61         d[x] = inf;
 62     d[S] = 0, v[S] = 1, q[0] = S;
 63     for(l = r = 0; l != (r + 1) % N; ++l %= N) {
 64         for (x = first[q[l]]; x; x = e[x].next)
 65             if (d[q[l]] + e[x].cost < d[y = e[x].to] && e[x].f) {
 66                 d[y] = d[q[l]] + e[x].cost, g[y] = x;
 67                 if (!v[y])
 68                     q[++r %= N] = y, v[y] = 1;
 69             }
 70         v[q[l]] = 0;
 71     }
 72     return d[T] != inf;
 73 }
 74
 75 inline int work() {
 76     int res = 0;
 77     while (spfa())
 78         res += calc() * d[T];
 79     return res;
 80 }
 81
 82 void build_graph() {
 83     int i, j, x, now = 0;
 84     for (i = 1; i <= n; ++i)
 85         for (j = 1; j <= n; ++j) {
 86             x = read();
 87             if (j <= i) continue;
 88             sum[++now] = i + j;
 89             if (x == 2) {
 90                 Add_Edges(now, i + m, 1, 0), Add_Edges(now, j + m, 1, 0);
 91                 ++in[i], ++in[j];
 92             } else
 93             if (x == 1) Add_Edges(now, i + m, 1, 0), ++in[i];
 94             else Add_Edges(now, j + m, 1, 0), ++in[j];
 95         }
 96     for (i = 1; i <= m; ++i)
 97         Add_Edges(S, i, 1, 0);
 98     for (i = 1; i <= n; ++i)
 99         for (j = 1; j <= in[i]; ++j)
100             Add_Edges(i + m, T, 1, 2 * j - 1);
101 }
102
103 void make_ans() {
104     int a[Num][Num], i, j, x;
105     memset(a, 0, sizeof(a));
106     for (i = 1; i <= m; ++i)
107         for (x = first[i]; x; x = e[x].next)
108             if (!e[x].f) a[e[x].to - m][sum[i] - e[x].to + m] = 1;
109     for (i = 1; i <= n; ++i) {
110         for (j = 1; j <= n; ++j)
111             printf("%d ", a[i][j]);
112         printf("\n");
113     }
114 }
115
116 int main() {
117     n = read(), m = n * (n - 1) / 2;
118     S = n + m + 1, T = S + 1;
119     build_graph();
120     printf("%d\n", (n * (n - 1) * (n - 2) / 3 + m - work()) / 2);
121     make_ans();
122     return 0;
123 }

(p.s.  为何这么慢= =我去。。)

时间: 2024-08-05 11:39:00

BZOJ2597 [Wc2007]剪刀石头布的相关文章

BZOJ2597 [Wc2007]剪刀石头布(最小费用最大流)

题目大概是说n个人两两进行比赛,问如何安排几场比赛的输赢使得A胜B,B胜C,C胜A这种剪刀石头布的三元组最多. 这题好神. 首先,三元组总共有$C_n^3$个 然后考虑最小化不满足剪刀石头布条件的三元组个数: 对于三个人构不成剪刀石头布现象,当且仅当,其中一个人赢了其他两个人 而由于这是完全图,如果一个人赢了$x_i$场那么包含这个人不满足剪刀石头布现象的三元组就有$C_{x_i}^2$个 所以目的就是最小化$\sum C_{x_i}^2$,即$\sum x_i^2-C_n^2$,其中$C_n^

【BZOJ 2597】 [Wc2007]剪刀石头布

2597: [Wc2007]剪刀石头布 Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special Judge Submit: 492  Solved: 227 [Submit][Status] Description 在一些一对一游戏的比赛(如下棋.乒乓球和羽毛球的单打)中,我们经常会遇到A胜过B,B胜过C而C又胜过A的有趣情况,不妨形象的称之为剪刀石头布情况.有的时候,无聊的人们会津津乐道于统计有多少这样的剪刀石头布情况发生,即有多少对无序三元组

[Wc2007]剪刀石头布

[Wc2007]剪刀石头布 http://www.lydsy.com/JudgeOnline/problem.php?id=2597 Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special Judge Description 在一些一对一游戏的比赛(如下棋.乒乓球和羽毛球的单打)中,我们经常会遇到A胜过B,B胜过C而C又胜过A的有趣情况,不妨形象的称之为剪刀石头布情况.有的时候,无聊的人们会津津乐道于统计有多少这样的剪刀石头布情况发生,即有多少对

2597: [Wc2007]剪刀石头布

2597: [Wc2007]剪刀石头布 链接 分析: 费用流. 首先转化一下问题,整张图最优的情况是存在$C_n^3$个,即任意3个都行,然后考虑去掉最少不满足的三元环. 如果u赢了v,u向v连一条边,如果v有k条入边,那么说明少了$C_k^2$个三元环,所对每场比赛分配度数,求最小费用最大流. 具体地:S向每场比赛连容量为1,花费为0的边:每场比赛向两个人连容量为1,花费为0的边:每个人因为度数不同,花费不同,所以差分后建边. 代码: #include<cstdio> #include<

BZOJ 2597 WC2007 剪刀石头布 费用流

题目大意:给出一张竞赛图中的其中几条单向边,剩下的边随意定向.问最多可以形成多少三元环. 思路:对于任意三个点来说,他们组成了三元环,当且仅当这些点的入度=处度 = 1.如果没有组成三元环,只需要改变这其中任意一条边的方向,使得一个点的入度变成2,一个点的出度变成2.我们只需要算出有多少三个点中有一个点的入度为2的就可以了,并最小化这个东西. 通过公式:ans=C(n,3)-ΣC(degree[x],2)可以发现,我们只需要让每个点的入度尽可能小.由此想到费用流模型(我怎么想不到..) 类似于x

Luogu P4249 [WC2007]剪刀石头布

Link 先把题意抽象一下:给定一个存在一部分为定向的边的竞赛图,最大化它的三元环个数. 我们知道竞赛图的三元环个数为\({n\choose 3}-\sum\limits_{i=1}^n{deg_i\choose 2}\). 对于一条未定向的边\((u,v)\),它会使\(u,v\)其中一个点的度数加一. 对于一个点而言,随着度数的增加,度数加一使得三元环减少的个数也是在增加的,也就是说这是一个凸函数. 那么直接费用流就行了,建图就是凸函数差分的那一套方法. #include<queue> #

YCB 的暑期计划

前言 YCB现在很弱(TAT) 暑假有一个月,赶快狂补一下. 大概的计划如下: 首先前期会以数据结构为主,毕竟代码能力太弱,涉及内容:线段树分治.二进制分组.KD-Tree. 等数据结构做到没有智商的时候加入一波数论,内容为 杜教筛.min_25筛. 然后中途小清新一下,做一些 组合博弈与构造题. 接着继续练代码能力,顺便学一些神奇的暴力:启发式合并.dsu on tree . 然后图论也忘的差不多了,就回过头去学点新东西,大概会有spfa判负环.0/1分数规划.差分约束. 估计这个时候也没有什

题解#3

感觉自己弱得没救了...求神犇解救T_T 1 2597: [Wc2007]剪刀石头布 补集转化之后就是费用流了.我比较逗方案WA了两发. 1 int n,m,k,mincost,tot=1,cnt,s,t,win[maxn],a[maxn][maxn],b[maxn][maxn],head[maxm],d[maxm],from[2*maxm]; 2 3 bool v[maxm]; 4 5 queue<int>q; 6 7 struct edge{int from,go,next,v,c;}e[

【BZOJ2597】【Wc2007】剪刀石头布 费用流,没写zkw卡时过

题解,比较常规式是费用流,没写那个神贪心. 首先是三元环需要取补集,先C(n,3)算出总环数,然后减去失败的三元环. 我们发现在一个三元环中,如果有某个选手入度(or 出度)为2,那么就会破坏这个环. 所以当选手有x个度时,就会破坏∑(i∈[0,x])个三元环(0+....+x-1),P.S.这个是C(x,2)推出来的. 建图: 第一层源点 到下一层每个点若干条边 条数: 那个选手可能赢的次数, 费用: 第i条边费用i-1, 流量: 1 第二层选手 到可能赢的每个对应竞赛建边 条数: 1 费用: