[WC2007]剪刀石头布(最大流)
一句话题意:给定一张图,每两点之间有一条有向边或无向边,把所有无向边定向,使图中三元环个数尽量多
因为原图是一个完全图,假设图中任意三点都能构成三元环,那么途中三元环的个数为:\(\binom{n}{3}\)。
那么如果一个三元组不是三元环,那么有一个点的出度为2。
我们假设一个点的出度为d,那么对于这个点,三元环会减少\(\frac{d (d-1)}{2}\)
所以三元环的数量为:\(\binom{n}{3}- \sum_{i=1}^n\binom{d[i]}{2}=\binom{n}{3}- \sum_{i=1}^n\frac{d[i] (d[i]-1)}{2}\)
所以我们要最小化:$ \sum_{i=1}^n\frac{d[i] (d[i]-1)}{2}$的值。
怎么做呢?
如果我们对于一条无向边,可能让u出度+1,也可能让v出度+1,非黑即白,所以我们可以考虑费用流。
观察柿子\(\frac{d[i] (d[i]-1)}{2}\),容(hen)易(nan)想到小学等差数列求和公式,于是我们可以将一个点的贡献看成\((0+1+2+3+……+d[i]-1)\)
把每一条边看成一个点,从源点向每条边连一条容量为1,费用为0的边。
对于一条无向边,往u,v分别建一条容量为1,费用为0的边。
有向边则把边和v建一条容量为1,费用为0的边。
每个点向汇点连n条容量为1,费用为0-(n-1)递增的边,表示上面的等差数列(可以表示出任何出度的情况)
最后就是费用流的板子了
代码如下:
#include<bits/stdc++.h>
using namespace std;
#define il inline
#define re register
#define inf 123456789
#define debug printf("Now is Line : %d\n",__LINE__)
il int read()
{
re int x=0,f=1; re char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=x*10+c-48,c=getchar();
return x*f;
}
#define maxn 105
#define maxm 105*105
struct edge
{
int v,w,val,next;
}e[maxm<<3];
int n,a[maxn][maxn],S,T,maxflow,cost,vis[maxm],dis[maxm],head[maxm],cnt=1,pa;
il void add(int u,int v,int val,int w)
{
e[++cnt]=(edge){v,w,val,head[u]};
head[u]=cnt;
e[++cnt]=(edge){u,-w,0,head[v]};
head[v]=cnt;
}
queue<int>q;
il bool spfa()
{
memset(vis,0,sizeof(vis));
memset(dis,127,sizeof(dis));
dis[S]=0; q.push(S);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(re int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
if(dis[v]>dis[u]+e[i].w&&e[i].val>0)
{
dis[v]=dis[u]+e[i].w;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
return dis[T]!=2139062143;
}
il int dfs(int u,int mi)
{
if(u==T)
{
vis[T]=1;
return mi;
}
vis[u]=1;
int use=0;
for(re int i=head[u];i;i=e[i].next)
{
int v=e[i].v;
if((!vis[v]||v==T)&&e[i].val>0&&dis[v]==dis[u]+e[i].w)
{
int low=dfs(v,min(mi-use,e[i].val));
if(low>0)
{
cost+=low*e[i].w;
e[i].val-=low; e[i^1].val+=low;
use+=low;
}
}
}
return use;
}
il void dinic()
{
while(spfa())
{
vis[T]=1;
while(vis[T])
{
memset(vis,0,sizeof(vis));
dfs(S,inf);
}
}
int ans=((n-1)*(n-2)*n)/6;
ans-=cost;
printf("%d\n",ans);
}
int main()
{
n=read(); T=n*n+n+1;
for(re int i=1;i<=n;++i)
{
for(re int j=1;j<=n;++j)
{
a[i][j]=read();
if(i>=j) continue;
if(a[i][j]==2)
{
add(S,(i-1)*n+j,1,0);
add((i-1)*n+j,n*n+i,1,0);
add((i-1)*n+j,n*n+j,1,0);
}
else if(a[i][j]==1) add(S,n*n+j,1,0);
else add(S,n*n+i,1,0);
}
}
for(re int i=1;i<=n;++i)
{
for(re int j=0;j<n;++j) add(n*n+i,T,1,j);
}
dinic();
for(re int i=1;i<=n;++i)
{
for(re int j=i+1;j<=n;++j)
{
if(a[i][j]<2) continue;
for(re int k=head[(i-1)*n+j];k;k=e[k].next)
{
if(e[k].v&&e[k].val==0)
{
a[i][j]=(e[k].v-n*n==j);
a[j][i]=a[i][j]^1;
}
}
}
}
for(re int i=1;i<=n;++i,puts(""))
{
for(re int j=1;j<=n;++j) printf("%d ",a[i][j]);
}
return 0;
}
[WC2007]剪刀石头布(最大流)的更多相关文章
- BZOJ.2597.[WC2007]剪刀石头布(费用流zkw)
BZOJ 洛谷 \(Description\) 给定一张部分边方向已确定的竞赛图.你需要给剩下的边确定方向,使得图中的三元环数量最多. \(n\leq100\). \(Solution\) 这种选择之 ...
- bzoj 2597 [Wc2007]剪刀石头布——费用流
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2597 三个人之间的关系,除了“剪刀石头布”,就是有一个人赢了2局:所以考虑算补集,则每个人对 ...
- [WC2007]剪刀石头布——费用流
比较有思维含量的一道题 题意:给混合完全图定向(定向为竞赛图)使得有最多的三元环 三元环条件要求比较高,还不容易分开处理. 正难则反 考虑,什么情况下,三元组不是三元环 一定是一个点有2个入度,一个点 ...
- BZOJ 2597: [Wc2007]剪刀石头布(费用流)
传送门 解题思路 考虑全集-不能构成三元环的个数.如果三个点不能构成三元环,一定有一个点的入度为\(2\),继续扩展,如果一个点的度数为\(3\),则会失去3个三元环.对于一个点来说,它所产生的不能构 ...
- [bzoj2597][Wc2007]剪刀石头布_费用流
[Wc2007]剪刀石头布 题目大意:https://www.lydsy.com/JudgeOnline/problem.php?id=2597 题解: 发现直接求三元环不好求,我们考虑任选三个点不是 ...
- 2597: [Wc2007]剪刀石头布
2597: [Wc2007]剪刀石头布 链接 分析: 费用流. 首先转化一下问题,整张图最优的情况是存在$C_n^3$个,即任意3个都行,然后考虑去掉最少不满足的三元环. 如果u赢了v,u向v连一条边 ...
- [Wc2007]剪刀石头布
[Wc2007]剪刀石头布 http://www.lydsy.com/JudgeOnline/problem.php?id=2597 Time Limit: 20 Sec Memory Limit: ...
- 【BZOJ2597】[Wc2007]剪刀石头布 最小费用流
[BZOJ2597][Wc2007]剪刀石头布 Description 在一些一对一游戏的比赛(如下棋.乒乓球和羽毛球的单打)中,我们经常会遇到A胜过B,B胜过C而C又胜过A的有趣情况,不妨形象的称之 ...
- [Wc2007]剪刀石头布[补集转化+拆边]
2597: [Wc2007]剪刀石头布 Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 1157 Solved: ...
- BZOJ2597 [Wc2007]剪刀石头布(最小费用最大流)
题目大概是说n个人两两进行比赛,问如何安排几场比赛的输赢使得A胜B,B胜C,C胜A这种剪刀石头布的三元组最多. 这题好神. 首先,三元组总共有$C_n^3$个 然后考虑最小化不满足剪刀石头布条件的三元 ...
随机推荐
- Android项目实战(一): SpannableString与SpannableStringBuilder(转)
前言: 曾经在一些APP中的一些类似“帮助”“关于”的界面看过一行文字显示不同的颜色的效果,如下效果: 本软件是一款高.大.上的社区类软件. 一般来说,这应该是由一个TextView来显示的,但是自己 ...
- Error occurred during initialization of VM Could not reserve enough space for 2097152KB object heap
ionic build Android后的报错问题 ionic 升级了splashscreen和statusbar的插件后,执行ionic build android会一直报打包错误.原因是过低的An ...
- SpringBoot实现全文搜索
• 全文搜索 • solr安装 • solr中文分词 • solr数据库导入 • solr数据查询 • solrj接口调用 1:
- 测试系统工程师TSE需要具备的四项能力
文/杨学明 如今,国内所有的研发型的公司都有测试部门,无论测试团队大小,都有测试组长,测试经理,测试工程师等头衔,但随着产品和业务的质量要求越来越高,产品的市场竞争越来越激烈,公司领导对产品测试的要求 ...
- Linux内核最新的连续内存分配器(CMA)——避免预留大块内存【转】
在我们使用ARM等嵌入式Linux系统的时候,一个头疼的问题是GPU,Camera,HDMI等都需要预留大量连续内存,这部分内存平时不用,但是一般的做法又必须先预留着.目前,Marek Szyprow ...
- LinuxCPU性能监控工具---mpstat
mpstat是 Multiprocessor Statistics的缩写,是实时系统监控工具.其报告与CPU的一些统计信息,这些信息存放在/proc/stat文件中.在多CPU系统里,其不但能查看所有 ...
- LeetCode算法题-Reshape the Matrix(Java实现)
这是悦乐书的第264次更新,第277篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第131题(顺位题号是566).在MATLAB中,有一个非常有用的函数叫做'reshap ...
- MySql 学习之路-聚合函数
下面是mysql 数据库中经常用到的聚合函数的简单实例 -- 创建学生表 create table student ( id int primary key auto_increment commen ...
- Offset Management For Apache Kafka With Apache Spark Streaming
An ingest pattern that we commonly see being adopted at Cloudera customers is Apache Spark Streaming ...
- day8-基础函数的学习(三)
开始今日份总结 今日目录 1.生成器 2.列表推导式 3.匿名函数 4.装饰器 开始今日份总结 1.生成器 1.1 生成器的定义 定义:生成器本质就是迭代器,生成器是自己用python代码写的迭代器 ...