题目链接

BZOJ2597

题解

orz思维差

既然是一张竞赛图,我们选出任意三个点都可能成环

总方案数为

\[{n \choose 3}
\]

如果三个点不成环,会发现它们的度数是确定的,入度分别为\(2,1,0\),出度为\(0,1,2\)

所以一个点的任意两个入度,都会对答案产生一个负的贡献

所以三元环数量为

\[{n \choose 3} - \sum\limits_{i = 1}^{n} {inde[i] \choose 2}
\]

我们要最大化三元环数目,就要最小化\(\sum\limits_{i = 1}^{n} {inde[i] \choose 2}\)

考虑建模,使用费用流

每条边可以将入度分给,也仅可以分配给两端点中的一个

我们就每条边建一个点,从\(S\)向每条边建出来的点连一条\((1,0)\)的边,表示能产生一个流量

然后该边的点向那两个端点分别连一条\((1,0)\)的边,表示能产生\(1\)个入度

然后考虑每产生一个入度的影响

考虑到

\[{x \choose 2} - {x - 1 \choose 2} = x - 1
\]

所以每增加一个入度,使得入度为\(x\)时,会多产生\(x - 1\)个贡献

按照费用流的套路,我们对每个点每一种度数建一条到\(T\)的边(1,x - 1),表示消耗这么多三元环

按照费用流的性质,一定会优先选择权值较小的边,也就是逐层增加

建图时,还要考虑原来已有的边

然后就做完了

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<map>
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define mp(a,b) make_pair<int,int>(a,b)
#define cls(s) memset(s,0,sizeof(s))
#define cp pair<int,int>
#define LL long long int
using namespace std;
const int maxn = 11005,maxm = 100005,INF = 1000000000;
inline int read(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
return out * flag;
}
int h[maxn],ne = 1;
struct EDGE{int from,to,nxt,f,w;}ed[maxm];
inline void build(int u,int v,int f,int w){
ed[++ne] = (EDGE){u,v,h[u],f,w}; h[u] = ne;
ed[++ne] = (EDGE){v,u,h[v],0,-w}; h[v] = ne;
}
int q[maxn * 10],head,tail;
int p[maxn],vis[maxn],S,T;
int d[maxn],minf[maxn];
int mincost(){
int cost = 0,flow = 0;
while (true){
for (int i = S; i <= T; i++) d[i] = minf[i] = INF,vis[i] = false;
d[S] = 0; q[head = tail = 0] = S;
int u;
while (head <= tail){
u = q[head++];
vis[u] = false;
Redge(u) if (ed[k].f && d[u] + ed[k].w < d[to = ed[k].to]){
minf[to] = min(minf[u],ed[k].f);
p[to] = k; d[to] = d[u] + ed[k].w;
if (!vis[to]) q[++tail] = to,vis[to] = true;
}
}
if (d[T] == INF) break;
flow += minf[T]; cost += d[T] * minf[T];
u = T;
while (u != S){
ed[p[u]].f -= minf[T];
ed[p[u] ^ 1].f += minf[T];
u = ed[p[u]].from;
}
}
return cost;
}
int n,G[105][105],de[105],N,a[maxn],b[maxn];
int main(){
n = read();
REP(i,n) REP(j,n){
G[i][j] = read();
if (i == j) continue;
if (!G[i][j]) de[i]++;
else if (G[i][j] == 2 && i < j) N++,a[N] = i,b[N] = j;
}
S = 0; T = N + n + 1;
REP(i,N) build(S,i,1,0),build(i,N + a[i],1,0),build(i,N + b[i],1,0);
REP(i,n){
for (int j = de[i] + 1; j <= n; j++)
build(N + i,T,1,j - 1);
}
int ans = n * (n - 1) * (n - 2) / 6;
REP(i,n) if (de[i] > 1) ans -= de[i] * (de[i] - 1) / 2;
ans -= mincost();
printf("%d\n",ans);
REP(i,N){
Redge(i) if ((to = ed[k].to) > N && !ed[k].f){
if (to - N == a[i]) G[a[i]][b[i]] = 0,G[b[i]][a[i]] = 1;
else G[a[i]][b[i]] = 1,G[b[i]][a[i]] = 0;
break;
}
}
for (int i = 1; i <= n; i++,puts("")){
for (int j = 1; j <= n; j++){
printf("%d",G[i][j]);
if (j < n) putchar(' ');
}
}
return 0;
}

BZOJ2597 [Wc2007]剪刀石头布 【费用流】的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. bzoj2597: [Wc2007]剪刀石头布(费用流)

    传送门 不得不说这思路真是太妙了 考虑能构成三元组很难,那我们考虑不能构成三元组的情况是怎么样 就是说一个三元组$(a,b,c)$,其中$a$赢两场,$b$赢一场,$c$没有赢 所以如果第$i$个人赢 ...

  7. Luogu4249 WC2007 石头剪刀布 费用流

    传送门 考虑竞赛图三元环计数,设第\(i\)个点的入度为\(d_i\),根据容斥,答案为\(C_n^3 - \sum C_{d_i}^2\) 所以我们需要最小化\(\sum C_{d_i}^2\) 考 ...

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

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

  9. BZOJ2597 WC2007剪刀石头布(费用流)

    考虑使非剪刀石头布情况尽量少.设第i个人赢了xi场,那么以i作为赢家的非剪刀石头布情况就为xi(xi-1)/2种.那么使Σxi(xi-1)/2尽量小即可. 考虑网络流.将比赛建成一排点,人建成一排点, ...

随机推荐

  1. Manual install on Windows 7 with Apache and MySQL

    These are instructions for installing on Windows 7 desktop (they may also be useful for a server ins ...

  2. 「题目代码」P1060~P1065(Java)

    P1060 谭浩强C语言(第三版)习题7.5 注意行末空格. import java.util.*; import java.io.*; import java.math.*; import java ...

  3. PHP使用Redis消息队列

    1.redis安装 参考:菜鸟教程http://www.runoob.com/redis/redis-install.html 2.安装php的redis扩展 1)phpinfo()查看php版本信息 ...

  4. RabbitMQ基础教程之Spring&JavaConfig使用篇

    RabbitMQ基础教程之Spring使用篇 相关博文,推荐查看: RabbitMq基础教程之安装与测试 RabbitMq基础教程之基本概念 RabbitMQ基础教程之基本使用篇 RabbitMQ基础 ...

  5. C# 中访问修饰符

    1.public 完全公开的,公共的 2. private 私有的,只能在当前类的内部访问, 不可修饰类 3.protected 受保护的,只能在当前类的内部以及其子类中访问,不能用来修饰类 4.in ...

  6. python程序设计——函数设计与调用

    一.函数定义与调用 def 函数名([参数列表]): '''注释''' 函数体 # 输出小于n的斐波那契数 >>def fib(n): a,b=1,1 while a < n: pr ...

  7. Python入门(5)

    导览: 函数 集合 迭代器与生成器 模块 一.函数 只要学过其他编程语言应该对函数不太陌生,函数在面向过程的编程语言中占据了极重要的地位,可以说没有函数,就没有面向过程编程,而在面向对象语言中,对象的 ...

  8. dice2win

    触发交易 转0个 https://etherscan.io/tx/0x784e80167353a886183106cbe3bd15e614cafdb5d6885ccd101177aa0f937a36 ...

  9. C#调用mingw的so库时无法加载DLL###.so 找不到指定的模块

    使用C#调用mingw的so,报了c# 无法加载DLL“###.so”,: 找不到指定的程序. (异常来自 HRESULT:0x8007007E)开始以为是dll路径问题,使用全路径确认正确后仍然无法 ...

  10. 团队协作第八周个人PSP

    11.3 --11.9本周例行报告 1.PSP(personal software process )个人软件过程. 类型 任务 开始时间                结束时间 中断时间 实际用时 ...