2597: [Wc2007]剪刀石头布

Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special Judge
Submit: 1016  Solved: 477
[Submit][Status][Discuss]

Description

在一些一对一游戏的比赛(如下棋、乒乓球和羽毛球的单打)中,我们经常会遇到A胜过B,B胜过C而C又胜过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赢了j,0表示i负于j,与输入矩阵不同的是,在这个矩阵中没有表示比赛尚未进行的数字2;对角线上的数字都是0。输出矩阵要保证合法,不能发生矛盾。

Sample Input

3
0 1 2
0 0 2
2 2 0

Sample Output

1
0 1 0
0 0 1
1 0 0

HINT

100%的数据中,N≤ 100。

Source

Solution

这道题,直接最大化剪刀石头布的数量很麻烦,所以可以考虑最小化不是剪刀石头布的数量,所以可以考虑利用最小费用流。

考虑如果一个人赢了$x_{i}$场,那么最后不是剪刀石头布的数量就是$\sum \frac{x_{i}*(x_{i}-1)}{2}$,所以就是最小化这个量.

建图很显然,对于一场比赛$<i,j>$新建一个节点,如果$<i,j>$确定,则向胜利一方连容量$1$,费用$0$;如果不确定则都连容量$1$,费用$0$;

然后源点$S$向每场比赛连容量$1$,费用$0$;每个人向$T$连边容量为$N$,限制费用.

问题在于如何限制费用另其满足对答案的贡献为$\frac{x_{i}*(x_{i}-1)}{2}$,然后我想到对于求$\sum_{i=1}^{N}=\frac{N*(N+1)}{2}$,然后如果令$N=N-1$,答案正好是$\frac{N*(N-1)}{2}$,所以就可以拆成$N$条边,费用依次是$0..N-1$

然后就可以了.最后方案统计一下就好,即统计比赛$<i,j>$流向$i$还是流向$j$.

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
inline int read()
{
int x=0,f=1; char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();}
return x*f;
}
#define MAXN 11000
#define MAXM 500010
#define INF 0x7fffffff
int N,mp[110][110],id[110][110],e[10100][110];
struct EdgeNode{int next,to,from,cap,cost;}edge[MAXM<<1];
int head[MAXN],cnt=1;
inline void AddEdge(int u,int v,int w,int c) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v; edge[cnt].from=u; edge[cnt].cost=c; edge[cnt].cap=w;}
inline void InsertEdge(int u,int v,int w,int c) {AddEdge(u,v,w,c); AddEdge(v,u,0,-c);}
int mark[MAXM],dis[MAXM],Flow,Cost,S,T;
inline bool SPFA()
{
for (int i=S; i<=T; i++) dis[i]=INF,mark[i]=0;
queue<int>q;
q.push(S); dis[S]=0; mark[S]=1;
while (!q.empty())
{
int now=q.front(); q.pop(); mark[now]=0;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].cap && dis[edge[i].to]>dis[now]+edge[i].cost)
{
dis[edge[i].to]=dis[now]+edge[i].cost;
if (!mark[edge[i].to]) q.push(edge[i].to),mark[edge[i].to]=1;
}
}
return dis[T]!=INF;
}
inline int DFS(int loc,int low)
{
mark[loc]=1;
if (loc==T) return low;
int used=0,w;
for (int i=head[loc]; i; i=edge[i].next)
if (edge[i].cap && !mark[edge[i].to] && dis[edge[i].to]==dis[loc]+edge[i].cost)
{
w=DFS(edge[i].to,min(edge[i].cap,low-used));
edge[i].cap-=w; edge[i^1].cap+=w; used+=w; Cost+=w*edge[i].cost;
if (low==used) return used;
}
return used;
}
inline int ZKW()
{
int re=0;
while (SPFA())
{
mark[T]=1;
while (mark[T])
{
for (int i=S; i<=T; i++) mark[i]=0;
re+=DFS(S,INF);
}
}
return re;
}
int main()
{
N=read();
for (int i=1; i<=N; i++)
for (int j=1; j<=N; j++) mp[i][j]=read();
int ID=N;
for (int i=1; i<=N; i++)
for (int j=1; j<=N; j++) id[i][j]=++ID;
S=0; T=ID+1;
for (int i=1; i<=N; i++)
for (int j=i+1; j<=N; j++)
if (i!=j)
{
InsertEdge(S,id[i][j],1,0);
switch (mp[i][j])
{
case 1: InsertEdge(id[i][j],i,1,0); break;
case 0: InsertEdge(id[i][j],j,1,0); break;
case 2: InsertEdge(id[i][j],i,1,0); e[id[i][j]][i]=cnt-1;
InsertEdge(id[i][j],j,1,0); e[id[i][j]][j]=cnt-1; break;
}
}
for (int i=1; i<=N; i++)
for (int j=1; j<=N; j++) InsertEdge(i,T,1,j-1);
ZKW();
printf("%d\n",N*(N-2)*(N-1)/6-Cost);
for (int i=1; i<=N; i++)
for (int j=i+1; j<=N; j++)
if (mp[i][j]==2)
{
mp[i][j]=edge[e[id[i][j]][i]].cap==0;
mp[j][i]=mp[i][j]^1;
}
for (int i=1; i<=N; i++,puts(""))
for (int j=1; j<=N; j++) printf("%d ",mp[i][j]);
return 0;
}

  

【BZOJ-2597】剪刀石头布 最小费用最大流的更多相关文章

  1. bzoj 2597 剪刀石头布 —— 拆边费用流

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2597 不合法的三个人之间的关系就是一个人赢了两次: 记 \( deg[i] \) 表示第 \ ...

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

    题目大概是说n个人两两进行比赛,问如何安排几场比赛的输赢使得A胜B,B胜C,C胜A这种剪刀石头布的三元组最多. 这题好神. 首先,三元组总共有$C_n^3$个 然后考虑最小化不满足剪刀石头布条件的三元 ...

  3. BZOJ 2668 [cqoi2012]交换棋子 | 最小费用最大流

    传送门 BZOJ 2668 题解 同时分别限制流入和流出次数,所以把一个点拆成三个:入点in(x).中间点mi(x).出点ou(x). 如果一个格子x在初始状态是黑点,则连(S, mi(x), 1, ...

  4. BZOJ 3876 [AHOI/JSOI2014]支线剧情 (最小费用可行流)

    题面:洛谷传送门 BZOJ传送门 题目大意:给你一张有向无环图,边有边权,让我们用任意条从1号点开始的路径覆盖这张图,需要保证覆盖完成后图内所有边都被覆盖至少一次,求覆盖路径总长度的最小值 最小费用可 ...

  5. 【BZOJ】1221: [HNOI2001] 软件开发(最小费用最大流)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1221 先吐槽一下,数组依旧开小了RE:在spfa中用了memset和<queue>的版本 ...

  6. BZOJ 1927 星际竞速(最小费用最大流)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1927 题意:一个图,n个点.对于给出的每条边 u,v,w,表示u和v中编号小的那个到编号 ...

  7. BZOJ 1061 志愿者招募(最小费用最大流)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=1061 题意:申奥成功后,布布经过不懈努力,终于 成为奥组委下属公司人力资源部门的主管.布 ...

  8. bzoj 1877 [SDOI2009]晨跑(最小费用最大流)

    Description Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个十 ...

  9. bzoj 1927 [Sdoi2010]星际竞速(最小费用最大流)

    1927: [Sdoi2010]星际竞速 Time Limit: 20 Sec  Memory Limit: 259 MBSubmit: 1576  Solved: 954[Submit][Statu ...

随机推荐

  1. JDBC介绍

    1.DriverManager用来建立和数据库的链接以及管理JDBC驱动程序 driverManager的常用方法 方法 描述 registerDriver(Driver driver) 在Derve ...

  2. entityframework学习笔记--007-实体数据建模基础之继承关系映射TPT

    Table per Type Inheritance (TPT)建模 1.假设你有两张表与一张公共的表密切相关,如图7-1所示,Businiss表与eCommerce表.Retail表有1:0...1 ...

  3. 基于Nuclear的Web组件-Todo的十一种写法

    刀耕火种 刀耕火种是新石器时代残留的农业经营方式.又称迁移农业,为原始生荒耕作制. var TodoApp = Nuclear.create({ add: function (evt) { evt.p ...

  4. Gulp自动添加版本号

    推荐使用gulp-rev + gulp-rev-collector是比较方便的方法,结果如下: "/css/style.css" => "/dist/css/sty ...

  5. CALayer的m34 - 三维透视效果

    CATransform3D transform = CATransform3DIdentity; // 修改transform的m34达到透视效果 // - 1.0 / (500 ~ 1000 效果最 ...

  6. SQL Server 进阶 01 数据库的设计

    SQL Server 进阶 01 数据库的设计 本篇目录 课程内容回顾及介绍 为什么需要规范的数据库设计 设计数据库的步骤 绘制E-R(实体-关系)图 实体-关系模型 如何将E-R图转换为表 数据规范 ...

  7. db2学习笔记--数据类型对表的影响

    创建表的时为列选择合适的数据类型,可以提高数据库性能. 1.选择合适的数据类型,避免出现数据类型转换.例如日期,有人使用字符串来存放日期.时间戳,最后我们还要在程序中使用to_date做数据类型转换, ...

  8. 4-iscsi

    Iscsi 1.       创建lvm 2.       安装scsi服务端软件包 第一种(命令模式) 第二种(配置文件模式) 客户端 Node1 寻找scsi服务器上的储存设备 将scsi设备挂载 ...

  9. [原创]下拉框控件react-native-modal-dropdown更新历程

    前言 不知不觉从今年9月发布第一版控件到现在已经快3个月了 过去不断从开源社区索取,一直一直想着有机会一定要回报

  10. Ubuntu15.04安装不完全指南

    0x00. 烧盘 使用UltraISO(破解版)烧录到U盘里,设置电脑从U盘启动,即可安装. 安装时可能出现not COM32R image的命令行,“boot:” 后面直接输入live即可解决问题. ...