【bzoj2597】[Wc2007]剪刀石头布 动态加边费用流
题目描述
输入
输出
样例输入
3
0 1 2
0 0 2
2 2 0
样例输出
1
0 1 0
0 0 1
1 0 0
题解
动态加边费用流
首先正着想很难想,考虑反过来:已知最多可能产生的情况个数为$C_n^3$,求最少破坏多少个“剪刀石头布”情况?
然后考虑:对于任意的一个点(一只队伍),如果它有某两条出边,那么就破坏了这三个点之间的“剪刀石头布”情况。
而如果某个点的出度为d,则任意选出两条边的方案数为$C_d^2=\frac{d(d-1)}2$,差分得$C_d^2-C_{d-1}^2=d-1$。
于是我们可以使用使用拆边法来解决问题:S->每条边,容量为1,费用为0;每条边如果是有向边,则向指向发出边的点(赢的队伍),否则指向两个点,容量为1,费用为0。对于每个点,拆出n条边连向T,第i条边的容量为i-1。
然后跑最小费用流出解。由于直接跑会TLE,所以使用动态加边来优化。
最后满流的边指向的队伍就是赢的队伍。
#include <cstdio>
#include <cstring>
#include <queue>
#define N 11000
#define M 2200000
#define pos(i , j) (i - 1) * n + j
using namespace std;
queue<int> q;
int head[N] , to[M] , val[M] , cost[M] , next[M] , cnt = 1 , s , t , dis[N] , from[N] , pre[N] , ans[110][110];
void add(int x , int y, int v , int c)
{
to[++cnt] = y , val[cnt] = v , cost[cnt] = c , next[cnt] = head[x] , head[x] = cnt;
to[++cnt] = x , val[cnt] = 0 , cost[cnt] = -c , next[cnt] = head[y] , head[y] = cnt;
}
bool spfa()
{
int x , i;
memset(from , -1 , sizeof(from));
memset(dis , 0x3f , sizeof(dis));
dis[s] = 0 , q.push(s);
while(!q.empty())
{
x = q.front() , q.pop();
for(i = head[x] ; i ; i = next[i])
if(val[i] && dis[to[i]] > dis[x] + cost[i])
dis[to[i]] = dis[x] + cost[i] , from[to[i]] = x , pre[to[i]] = i , q.push(to[i]);
}
return ~from[t];
}
int calc(int x)
{
int i;
for(i = head[x] ; i ; i = next[i])
if(!val[i])
return to[i];
return 0;
}
int mincost()
{
int ans = 0 , i , k;
while(spfa())
{
k = 1 << 30;
for(i = t ; i != s ; i = from[i]) k = min(k , val[pre[i]]);
ans += k * dis[t] , add(from[t] , t , 1 , cost[pre[t]] + 1);
for(i = t ; i != s ; i = from[i]) val[pre[i]] -= k , val[pre[i] ^ 1] += k;
}
return ans;
}
int main()
{
int n , i , j , x;
scanf("%d" , &n) , s = 0 , t = n * n + n + 1;
for(i = 1 ; i <= n ; i ++ )
{
for(j = 1 ; j <= n ; j ++ )
{
scanf("%d" , &x);
if(i < j)
{
add(s , pos(i , j) , 1 , 0);
if(x != 0) add(pos(i , j) , n * n + i , 1 , 0);
if(x != 1) add(pos(i , j) , n * n + j , 1 , 0);
}
}
}
for(i = 1 ; i <= n ; i ++ )
add(n * n + i , t , 1 , 0);
printf("%d\n" , n * (n - 1) * (n - 2) / 6 - mincost());
for(i = 1 ; i <= n ; i ++ )
for(j = 1 ; j <= n ; j ++ )
if(i < j)
x = calc(pos(i , j)) - n * n , ans[x][i + j - x] = 1;
for(i = 1 ; i <= n ; i ++ )
{
for(j = 1 ; j <= n ; j ++ ) printf("%d " , ans[i][j]);
printf("\n");
}
return 0;
}
【bzoj2597】[Wc2007]剪刀石头布 动态加边费用流的更多相关文章
- bzoj2879(动态加边费用流)
参考题解:http://blog.csdn.net/yxuanwkeith/article/details/52254602 //开始跑费用流用的dijkstra,一直错,后来发现动态加边后我不会处理 ...
- [bzoj2597][Wc2007]剪刀石头布_费用流
[Wc2007]剪刀石头布 题目大意:https://www.lydsy.com/JudgeOnline/problem.php?id=2597 题解: 发现直接求三元环不好求,我们考虑任选三个点不是 ...
- BZOJ2597 [Wc2007]剪刀石头布 【费用流】
题目链接 BZOJ2597 题解 orz思维差 既然是一张竞赛图,我们选出任意三个点都可能成环 总方案数为 \[{n \choose 3}\] 如果三个点不成环,会发现它们的度数是确定的,入度分别为\ ...
- bzoj2597: [Wc2007]剪刀石头布(费用流)
传送门 不得不说这思路真是太妙了 考虑能构成三元组很难,那我们考虑不能构成三元组的情况是怎么样 就是说一个三元组$(a,b,c)$,其中$a$赢两场,$b$赢一场,$c$没有赢 所以如果第$i$个人赢 ...
- 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尽量小即可. 考虑网络流.将比赛建成一排点,人建成一排点, ...
- bzoj2597: [Wc2007]剪刀石头布
Description 在一些一对一游戏的比赛(如下棋.乒乓球和羽毛球的单打)中,我们经常会遇到A胜过B,B胜过C而C又胜过A的有趣情况,不妨形象的称之为剪刀石头布情况.有的时候,无聊的人们会津津乐道 ...
- 【bzoj2879】[Noi2012]美食节 费用流+动态加边
原文地址:http://www.cnblogs.com/GXZlegend 题目描述 CZ市为了欢迎全国各地的同学,特地举办了一场盛大的美食节.作为一个喜欢尝鲜的美食客,小M自然不愿意错过这场盛宴.他 ...
- Codeforces 708D 上下界费用流
给你一个网络流的图 图中可能会有流量不平衡和流量>容量的情况存在 每调整一单位的流量/容量 需要一个单位的花费 问最少需要多少花费使得原图调整为正确(可行)的网络流 设当前边信息为(u,v,f, ...
随机推荐
- Java生成-zipf分布的数据集(自定义倾斜度,用作spark data skew测试)
1.代码 import java.io.Serializable; import java.util.NavigableMap; import java.util.Random; import jav ...
- 【extjs6学习笔记】0.3 准备:系统架构
- docker 配置国内镜像源 linux/mac/windows
部分内容来自:http://guide.daocloud.io/dcs/daocloud-9153151.html 加速器官方DaoCloud承诺:加速器服务永久免费且无流量限制 使用前提:注册Dao ...
- Android学习总结(十三) ———— ListView 简单用法
一.ListView的基本概念 在Android所有常用的原生控件当中,用法最复杂的应该就是ListView了,它专门用于处理那种内容元素很多,手机屏幕无法展示出所有内容的情况.ListView可以使 ...
- 洛谷 P1744 采购特价商品
题目背景 <爱与愁的故事第三弹·shopping>第一章. 题目描述 中山路店山店海,成了购物狂爱与愁大神的“不归之路”.中山路上有n(n<=100)家店,每家店的坐标均在-1000 ...
- 仿天猫淘宝的ShopNC好商城原生Android 客户端源码项目
开发环境:Android Studio 2.0 | Gradle 2.0.0最后更新:2016-04-28 简介:基于好商城V4的Android客户端 目前已完成的功能(概述): 1.启动页 -> ...
- Adding other views to UIButton
Q: I want to add some views to UIButton, for example multiple UILabels, UIImages etc. One I add thos ...
- ubuntu 14.04 安装npm
1. 安装 sudo apt install nodejs-legacy sudo apt install npm
- git快速入门(MAC系统,github,ssh key)
如果使用过svn的话,git大致可以认为是多了本地库的svn.git先本地提交commit到本地库,然后再push到远程服务器的库.git是分布式的代码管理工具,基于SSH协议.ssh的作用就是为了不 ...
- linx vim 文件操作 ubuntu server 软件源
mv /etc/danted.conf /etc/danted.conf.bak sudo wget https://files.cnblogs.com/files/marklove/danted.t ...