bzoj2597: [Wc2007]剪刀石头布(费用流)
不得不说这思路真是太妙了
考虑能构成三元组很难,那我们考虑不能构成三元组的情况是怎么样
就是说一个三元组$(a,b,c)$,其中$a$赢两场,$b$赢一场,$c$没有赢
所以如果第$i$个人赢了$w_i$场,那么总共的不能构成的三元组就是$\sum_i{w_i*(w_i-1)}{2}$
最大化满足的数量,就是最小化不满足的数量,就是最小化上面那个式子
那么我们考虑构建网络流
建源汇
对第$i$个人,从它向汇点连容量为$n$的边
对于每一对$i,j$之间的比赛建一个点$C_{i,j}$,如果这场比赛尚未进行,那么源点向$C_{i,j}$连容$1$费$0$的边,$C_{i,j}向$i$和$j$连容$1$费$0$的边,表示这场比赛只能改变一个点的赢的场数
我们要最小化上式,那么我们考虑在费用上做文章
每个点$i$向汇点连边,但因为费用的增加是一次比一次大的,所以我们考虑把这条边拆成$n$条边,容量为$1$费用分别为$0,1,2...$
因为费用流每一次都先增广最小的费用,所以只要求出最小费用最大流即可
//minamoto
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define inf 0x3f3f3f3f
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
const int N=,M=;
int head[N],Next[M],ver[M],edge[M],cost[M],tot=;
inline void add(int u,int v,int e,int c=){
ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e,cost[tot]=c;
ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=,cost[tot]=-c;
}
int dis[N],vis[N],cur[N],S,T,ans;
queue<int> q;
bool spfa(){
memset(dis,-,sizeof(dis));
memset(vis,,sizeof(vis));
memcpy(cur,head,sizeof(head));
q.push(T),dis[T]=,vis[T]=;
while(!q.empty()){
int u=q.front();q.pop(),vis[u]=;
for(int i=head[u];i;i=Next[i])
if(edge[i^]){
int v=ver[i],c=cost[i];
if(dis[v]<||dis[v]>dis[u]-c){
dis[v]=dis[u]-c;
if(!vis[v]) vis[v]=,q.push(v);
}
}
}
return ~dis[S];
}
int dfs(int u,int limit){
if(!limit||u==T) return limit;
int flow=,f;vis[u]=;
for(int i=cur[u];i;cur[u]=i=Next[i]){
int v=ver[i];
if(dis[v]==dis[u]-cost[i]&&!vis[v]&&(f=dfs(v,min(limit,edge[i])))){
flow+=f,limit-=f;
edge[i]-=f,edge[i^]+=f;
ans-=f*cost[i];
if(!limit) break;
}
}
vis[u]=;
return flow;
}
void zkw(){while(spfa()) dfs(S,inf);}
int mp[][],win[][],n,cnt;
int main(){
//freopen("testdata.in","r",stdin);
n=read();
for(int i=;i<=n;++i)
for(int j=;j<=n;++j)
mp[i][j]=read();
S=,cnt=n;
for(int i=;i<=n;++i)
for(int j=;j<i;++j){
add(S,++cnt,);
if(mp[i][j]==||mp[i][j]==) add(cnt,i,),win[j][i]=tot-;
if(mp[i][j]==||mp[i][j]==) add(cnt,j,),win[i][j]=tot-;
}
T=cnt+;
for(int i=;i<=n;++i)
for(int j=;j<n;++j)
add(i,T,,j);
ans=n*(n-)*(n-)/;
zkw();
printf("%d\n",ans);
for(int i=;i<=n;++i){
for(int j=;j<=n;++j)
printf("%s%d",j==?"":" ",!win[i][j]||edge[win[i][j]]?:);
putchar();
}
return ;
}
bzoj2597: [Wc2007]剪刀石头布(费用流)的更多相关文章
- BZOJ.2597.[WC2007]剪刀石头布(费用流zkw)
BZOJ 洛谷 \(Description\) 给定一张部分边方向已确定的竞赛图.你需要给剩下的边确定方向,使得图中的三元环数量最多. \(n\leq100\). \(Solution\) 这种选择之 ...
- [WC2007]剪刀石头布——费用流
比较有思维含量的一道题 题意:给混合完全图定向(定向为竞赛图)使得有最多的三元环 三元环条件要求比较高,还不容易分开处理. 正难则反 考虑,什么情况下,三元组不是三元环 一定是一个点有2个入度,一个点 ...
- BZOJ 2597: [Wc2007]剪刀石头布(费用流)
传送门 解题思路 考虑全集-不能构成三元环的个数.如果三个点不能构成三元环,一定有一个点的入度为\(2\),继续扩展,如果一个点的度数为\(3\),则会失去3个三元环.对于一个点来说,它所产生的不能构 ...
- bzoj 2597 [Wc2007]剪刀石头布——费用流
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2597 三个人之间的关系,除了“剪刀石头布”,就是有一个人赢了2局:所以考虑算补集,则每个人对 ...
- [bzoj2597][Wc2007]剪刀石头布_费用流
[Wc2007]剪刀石头布 题目大意:https://www.lydsy.com/JudgeOnline/problem.php?id=2597 题解: 发现直接求三元环不好求,我们考虑任选三个点不是 ...
- BZOJ2597 [Wc2007]剪刀石头布 【费用流】
题目链接 BZOJ2597 题解 orz思维差 既然是一张竞赛图,我们选出任意三个点都可能成环 总方案数为 \[{n \choose 3}\] 如果三个点不成环,会发现它们的度数是确定的,入度分别为\ ...
- Luogu4249 WC2007 石头剪刀布 费用流
传送门 考虑竞赛图三元环计数,设第\(i\)个点的入度为\(d_i\),根据容斥,答案为\(C_n^3 - \sum C_{d_i}^2\) 所以我们需要最小化\(\sum C_{d_i}^2\) 考 ...
- BZOJ2597 [Wc2007]剪刀石头布(最小费用最大流)
题目大概是说n个人两两进行比赛,问如何安排几场比赛的输赢使得A胜B,B胜C,C胜A这种剪刀石头布的三元组最多. 这题好神. 首先,三元组总共有$C_n^3$个 然后考虑最小化不满足剪刀石头布条件的三元 ...
- BZOJ2597 WC2007剪刀石头布(费用流)
考虑使非剪刀石头布情况尽量少.设第i个人赢了xi场,那么以i作为赢家的非剪刀石头布情况就为xi(xi-1)/2种.那么使Σxi(xi-1)/2尽量小即可. 考虑网络流.将比赛建成一排点,人建成一排点, ...
随机推荐
- VScode 为 *.cu文件 添加高亮及c++ intelligence相关操作的方法
问题:*.cu在VScode不能像*.cc或*.cpp一样在c++及c++ intelligence插件有关键字的高亮以及go to definition等的操作 解决方案:添加*.cu与*.cpp文 ...
- stl_stack.h
stl_stack.h // Filename: stl_stack.h // Comment By: 凝霜 // E-mail: mdl2009@vip.qq.com // Blog: http:/ ...
- noip模拟赛Bywzj52501 17.10.18
T1 rob 环形消灭虫子 先想出了一个n^2暴力 然后我们想到 如果从两个连续的点求解 则会出现仅有的两种结果 (因为这两种情况的交是全集) 当时因为Naive求了50次 #include<i ...
- ACM学习历程—ZOJ3777 Problem Arrangement(递推 && 状压)
Description The 11th Zhejiang Provincial Collegiate Programming Contest is coming! As a problem sett ...
- node-webkit开发基本步骤
详情请查看:http://www.heiboard.com/?p=2091
- CF 360 E Levko and Game —— 贪心+最短路
题目:http://codeforces.com/contest/360/problem/E 首先,每条边不是选 \( l[i] \) 就是选 \( r[i] \): 做法就是先把边权都设成 \( r ...
- Python:正则表达式(三)*、+、?的用法
一.功能*——表示匹配前面的字符0个或多个:+——表示前面的字符1个或多个:?——(1)放在其他字符后面:表示匹配0次或1次: (2)放在*.+后面:表示匹配尽可能少的字符 二.例 字符串fooooo ...
- 通过pip3安装ipython
操作系统:Centos7.4:ipython可以用来测试python语句,故需要安装. 首先需要安装epelde的扩展库: easy_install是由PEAK(Python Enterprise A ...
- Ruby中的include
Ruby中的include语句应注意以下两个问题: 1.include与文件无关.C语言中,#include预处理指令在编译期将一个文件的内容插入到另一个文件中.Ruby语句只是简单地产生一个指向指定 ...
- VisualGDB系列4:概述-Linux程序与VS
根据VisualGDB官网(https://visualgdb.com)的帮助文档大致翻译而成.主要是作为个人学习记录.有错误的地方,Robin欢迎大家指正. 本文将会阐述如何使用VisualGDB来 ...