题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2597

不合法的三个人之间的关系就是一个人赢了两次;

记 \( deg[i] \) 表示第 \( i \) 个人赢的次数,那么答案就是 \( C_{n}^{3} - \sum\limits_{i=1}^{n} C_{deg[i]}^{2} \)

对于不确定的关系,如果确定 \( x \) 赢,那么答案中减去的不合法情况又会多 \( deg[x] \) 种;

也就是第一次多 \( deg[x] \),第二次多 \( deg[x] + 1 \),第三次多 \( deg[x] + 2 \) ...

如果把这些作为费用,因为每次走费用最小的边,正好是第一次 \( deg[x] \),第二次 \( deg[x] + 1 \)...

于是把每条无向边作为一个点,提供1的流量给两个端点中的一个表示哪个赢,赢的端点 \( x \) 向汇点连一系列费用从 \( deg[x] \) 开始递增的边即可;

WA了一次还以为是写法太麻烦,正准备大改,突然发现输出格式不对...数字中间要加空格的。

代码如下:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int const xn=,xm=1e5+,xxn=,inf=0x3f3f3f3f;
int n,cnt,id[xxn][xxn],dis[xn],hd[xn],to[xm],nxt[xm],ct=,c[xm],w[xm];
int S,T,pre[xn],inc[xn],deg[xxn],num[xxn],sid[xxn][xxn];
bool vis[xn];
queue<int>q;
struct N{int u,v;}ed[xm];
int rd()
{
int ret=,f=; char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=; ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return f?ret:-ret;
}
void add(int x,int y,int z,int f){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct; w[ct]=z; c[ct]=f;}
bool bfs()
{
memset(dis,0x3f,sizeof dis);
memset(pre,,sizeof pre);
memset(inc,0x3f,sizeof inc);
dis[S]=; q.push(S); vis[S]=;
while(q.size())
{
int x=q.front(); q.pop(); vis[x]=;
for(int i=hd[x],u;i;i=nxt[i])
if(dis[u=to[i]]>dis[x]+w[i]&&c[i])
{
dis[u]=dis[x]+w[i];
pre[u]=i; inc[u]=min(inc[x],c[i]);
if(!vis[u])vis[u]=,q.push(u);
}
}
return dis[T]!=inf;
}
void up()
{
int x=T;
while(x!=S)
{
int i=pre[x];
c[i]-=inc[T]; c[i^]+=inc[T];
x=to[i^];
}
}
int main()
{
n=rd();
for(int i=;i<=n;i++)
for(int j=,d;j<=n;j++)
{
d=rd(); sid[i][j]=d; if(i>=j)continue;
if(d==)deg[i]++; else if(d==) deg[j]++;
else
{
id[i][j]=id[j][i]=++cnt;
ed[cnt].u=i,ed[cnt].v=j;
num[i]++; num[j]++;//possible win
}
}
S=; T=cnt+n+;
for(int i=;i<=cnt;i++)
{
add(S,i,,),add(i,S,,);
add(i,ed[i].u+cnt,,),add(ed[i].u+cnt,i,,);//+cnt
add(i,ed[i].v+cnt,,),add(ed[i].v+cnt,i,,);
}
int ans=;
for(int i=;i<=n;i++)ans+=deg[i]*(deg[i]-)/;
for(int i=cnt+;i<=cnt+n;i++)
for(int j=;j<=num[i-cnt];j++)//-cnt
add(i,T,deg[i-cnt]+j-,),add(T,i,,);//-cnt
while(bfs())ans+=dis[T]*inc[T],up();//*
printf("%d\n",n*(n-)*(n-)/-ans);
for(int i=;i<=n;i++,puts(""))
for(int j=;j<=n;j++)
{
if(sid[i][j]!=){printf("%d ",sid[i][j]); continue;}
int x=id[i][j],t;
for(int k=hd[x],u;k;k=nxt[k])
if(to[k]==i+cnt&&!c[k]){t=i; break;}//+cnt
else if(to[k]==j+cnt&&!c[k]){t=j; break;}
if(t==i)printf("1 "),sid[j][i]=;
else printf("0 "),sid[j][i]=;
}
return ;
}

bzoj 2597 剪刀石头布 —— 拆边费用流的更多相关文章

  1. [bzoj 1449] 球队收益(费用流)

    [bzoj 1449] 球队收益(费用流) Description Input Output 一个整数表示联盟里所有球队收益之和的最小值. Sample Input 3 3 1 0 2 1 1 1 1 ...

  2. [bzoj2597][Wc2007]剪刀石头布_费用流

    [Wc2007]剪刀石头布 题目大意:https://www.lydsy.com/JudgeOnline/problem.php?id=2597 题解: 发现直接求三元环不好求,我们考虑任选三个点不是 ...

  3. 【BZOJ4930】棋盘 拆边费用流

    [BZOJ4930]棋盘 Description 给定一个n×n的棋盘,棋盘上每个位置要么为空要么为障碍.定义棋盘上两个位置(x,y),(u,v)能互相攻击当前仅 当满足以下两个条件: 1:x=u或y ...

  4. bzoj 1070: [SCOI2007]修车 费用流

    1070: [SCOI2007]修车 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 2785  Solved: 1110[Submit][Status] ...

  5. BZOJ 3171 循环格(费用流)

    题意 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位置(r,c),你可以沿着箭头防线在格子间行走.即如果(r ...

  6. BZOJ 1070 修车 【费用流】

    Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同 的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序, ...

  7. BZOJ 1930 吃豆豆(费用流)

    首先这题的两条线不相交的限制可以去掉,因为如果相交的话把点换一换是不影响最终结果的. 剩下的费用流建图是显然的,把点拆为两个,建立超级源点s和源点ss汇点t,连边(s,ss,2,0). 对于每个点,连 ...

  8. BZOJ 1927 星际竞速(费用流)

    考虑费用流,题目要求走n个点都走完且恰好一次,显然流量的限制为n. 建立源点s和汇点t,并把每个星球拆成两个点i和i',分别表示已到达该点和经过该点. 对于能力爆发,建边(s,i',1,w). 对应高 ...

  9. BZOJ 1221 软件开发(费用流)

    容易看出这是显然的费用流模型. 把每天需要的餐巾数作为限制.需要将天数拆点,x’表示每天需要的餐巾,x’’表示每天用完的餐巾.所以加边 (s,x',INF,0),(x'',t,INF,0). 餐巾可以 ...

随机推荐

  1. java List的相关工具类

    1. <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</ar ...

  2. WCF基础之大型数据和流

    在WCF的实际应用中,有可能存在10M,100M甚至G级别的传输,这个时候我们就不得不考虑编码和传输模式,当然得选择相应的绑定(binding) 如上图所示,我可以直接使用系统提供的相应绑定,然后设置 ...

  3. 九度OJ 1191:矩阵最大值 (矩阵计算)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2361 解决:1179 题目描述: 编写一个程序输入一个mXn的矩阵存储并输出,并且求出每行的最大值和每行的总和. 要求把每行总和放入每行最 ...

  4. visual studio2017 无法添加引用 未能加载包ReferenceManagerPackage not such interface support 解决方法

    安装完visual studio 2017 后添加引用总是提示 未能加载包ReferenceManagerPackage, 这个问题困扰了两天,直到在网上看到了下面这一段 I just got thi ...

  5. Android笔记之使用Glide加载网络图片、下载图片

    Glide简介 不想说太多,真的很方便:P)可以节省我不少时间 GitHub地址:https://github.com/bumptech/glide 加载网络图片到ImageView Glide.wi ...

  6. 自定义ionic弹出框

    <img width="64" height="64" src="img/timg.jpg" style="border-r ...

  7. C语言程序设计50例(经典收藏)之1

    题目:有1.2.3.4个数字,能组成多少个互不相同且无重复数字的三位数?都是多少? 程序分析:可填在百位.十位.个位的数字都是1.2.3.4.组成所有的排列后再去 掉不满足条件的排列. #includ ...

  8. Kattis - fairdivision 【贪心】

    题意 有一堆人 要给他们的朋友 买一个生日礼物,然后 每个人 给出自己的最大负担额度 并且给出礼物总价 然后要给出一种解决方案 尽量让 所有人的支出都接近平均,如果实在无法平均,那就让 先来的人 多处 ...

  9. 操作系统原理2——OS结构

    操作系统原理2——OS结构   计算机系统是由硬件系统和软件系统两部分组成, 操作系统是软件系统的一个组成部分,它是直接在硬件系统的基础上工作的,所以在研究操作系统之前,先必须对计算机系统的结构有一个 ...

  10. LINQ 学习路程 -- 查询操作 Expression Tree

    表达式树就像是树形的数据结构,表达式树中的每一个节点都是表达式, 表达式树可以表示一个数学公式如:x<y.x.<.y都是一个表达式,并构成树形的数据结构 表达式树使lambda表达式的结构 ...