洛古

一句话题意:给定一张图,每两点之间有一条有向边或无向边,把所有无向边定向,使图中三元环个数尽量多

因为原图是一个完全图,假设图中任意三点都能构成三元环,那么途中三元环的个数为:\(\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]剪刀石头布(最大流)的更多相关文章

  1. BZOJ.2597.[WC2007]剪刀石头布(费用流zkw)

    BZOJ 洛谷 \(Description\) 给定一张部分边方向已确定的竞赛图.你需要给剩下的边确定方向,使得图中的三元环数量最多. \(n\leq100\). \(Solution\) 这种选择之 ...

  2. bzoj 2597 [Wc2007]剪刀石头布——费用流

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2597 三个人之间的关系,除了“剪刀石头布”,就是有一个人赢了2局:所以考虑算补集,则每个人对 ...

  3. [WC2007]剪刀石头布——费用流

    比较有思维含量的一道题 题意:给混合完全图定向(定向为竞赛图)使得有最多的三元环 三元环条件要求比较高,还不容易分开处理. 正难则反 考虑,什么情况下,三元组不是三元环 一定是一个点有2个入度,一个点 ...

  4. BZOJ 2597: [Wc2007]剪刀石头布(费用流)

    传送门 解题思路 考虑全集-不能构成三元环的个数.如果三个点不能构成三元环,一定有一个点的入度为\(2\),继续扩展,如果一个点的度数为\(3\),则会失去3个三元环.对于一个点来说,它所产生的不能构 ...

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

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

  6. 2597: [Wc2007]剪刀石头布

    2597: [Wc2007]剪刀石头布 链接 分析: 费用流. 首先转化一下问题,整张图最优的情况是存在$C_n^3$个,即任意3个都行,然后考虑去掉最少不满足的三元环. 如果u赢了v,u向v连一条边 ...

  7. [Wc2007]剪刀石头布

    [Wc2007]剪刀石头布 http://www.lydsy.com/JudgeOnline/problem.php?id=2597 Time Limit: 20 Sec  Memory Limit: ...

  8. 【BZOJ2597】[Wc2007]剪刀石头布 最小费用流

    [BZOJ2597][Wc2007]剪刀石头布 Description 在一些一对一游戏的比赛(如下棋.乒乓球和羽毛球的单打)中,我们经常会遇到A胜过B,B胜过C而C又胜过A的有趣情况,不妨形象的称之 ...

  9. [Wc2007]剪刀石头布[补集转化+拆边]

    2597: [Wc2007]剪刀石头布 Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1157  Solved:  ...

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

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

随机推荐

  1. Android项目实战(一): SpannableString与SpannableStringBuilder(转)

    前言: 曾经在一些APP中的一些类似“帮助”“关于”的界面看过一行文字显示不同的颜色的效果,如下效果: 本软件是一款高.大.上的社区类软件. 一般来说,这应该是由一个TextView来显示的,但是自己 ...

  2. 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 ...

  3. SpringBoot实现全文搜索

    • 全文搜索  • solr安装  • solr中文分词  • solr数据库导入  • solr数据查询  • solrj接口调用     1:

  4. 测试系统工程师TSE需要具备的四项能力

    文/杨学明 如今,国内所有的研发型的公司都有测试部门,无论测试团队大小,都有测试组长,测试经理,测试工程师等头衔,但随着产品和业务的质量要求越来越高,产品的市场竞争越来越激烈,公司领导对产品测试的要求 ...

  5. Linux内核最新的连续内存分配器(CMA)——避免预留大块内存【转】

    在我们使用ARM等嵌入式Linux系统的时候,一个头疼的问题是GPU,Camera,HDMI等都需要预留大量连续内存,这部分内存平时不用,但是一般的做法又必须先预留着.目前,Marek Szyprow ...

  6. LinuxCPU性能监控工具---mpstat

    mpstat是 Multiprocessor Statistics的缩写,是实时系统监控工具.其报告与CPU的一些统计信息,这些信息存放在/proc/stat文件中.在多CPU系统里,其不但能查看所有 ...

  7. LeetCode算法题-Reshape the Matrix(Java实现)

    这是悦乐书的第264次更新,第277篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第131题(顺位题号是566).在MATLAB中,有一个非常有用的函数叫做'reshap ...

  8. MySql 学习之路-聚合函数

    下面是mysql 数据库中经常用到的聚合函数的简单实例 -- 创建学生表 create table student ( id int primary key auto_increment commen ...

  9. 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 ...

  10. day8-基础函数的学习(三)

    开始今日份总结 今日目录 1.生成器 2.列表推导式 3.匿名函数 4.装饰器 开始今日份总结 1.生成器 1.1 生成器的定义 定义:生成器本质就是迭代器,生成器是自己用python代码写的迭代器 ...