[Wc2007]剪刀石头布

题目大意https://www.lydsy.com/JudgeOnline/problem.php?id=2597


题解

发现直接求三元环不好求,我们考虑任选三个点不是三元环的个数。

这样的话,必定是有一个点被其余两个点指,我们就根据这个来求。

又发现,最后的答案之和所有点的度数有关。

就是,$\sum C_{d_i}^{2}$。

紧接着,因为度数和是一定的。而且已经有了一些边。

现在就是有固定的度数可以分配,每个点有一个分配上限,怎么分配最少?

发现一个事,就是$C_{d_i + 1}^{2} - C_{d_i} ^ {2} < C_{d_i + 2}^{2} - C_{d_i + 1}^{2}$。

根据这个性质,我们就可以暴力连边费用流了。

我们就把权值的差当做费用,它肯定会从低往高走因为是最小费用,满足题意。

代码

#include <bits/stdc++.h>

#define N 11010 

#define M 500010 

using namespace std;

int head[N], to[M], pre[N], nxt[M], val[M], cst[M], tot = 1;

int S = N - 1, T = N - 2, dis[N];

bool vis[N];

queue <int> q;

char *p1, *p2, buf[100000];

#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )

int rd() {
int x = 0;
char c = nc();
while (c < 48) {
c = nc();
}
while (c > 47) {
x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
}
return x;
} inline void add2(int x, int y, int z, int w) {
to[ ++ tot] = y;
nxt[tot] = head[x];
val[tot] = z;
cst[tot] = w;
head[x] = tot;
} inline void add(int x, int y, int z, int w) {
add2(x, y, z, w);
add2(y, x, 0, -w);
} bool spfa() {
while (!q.empty()) {
q.pop();
}
memset(pre, 0, sizeof pre);
memset(dis, 0x3f, sizeof dis);
dis[S] = 0;
q.push(S);
while (!q.empty()) {
int x = q.front();
q.pop();
vis[x] = false;
for (int i = head[x]; i; i = nxt[i]) {
if (dis[to[i]] > dis[x] + cst[i] && val[i]) {
dis[to[i]] = dis[x] + cst[i];
pre[to[i]] = i ^ 1;
if (!vis[to[i]]) {
vis[to[i]] = true;
q.push(to[i]);
}
}
}
}
return pre[T];
} int mincost() {
int re = 0;
while (spfa()) {
int mdl = 0x3f3f3f3f;
for (int i = T; i != S; i = to[pre[i]]) {
mdl = min(mdl, val[pre[i] ^ 1]);
}
for (int i = T; i != S; i = to[pre[i]]) {
val[pre[i] ^ 1] -= mdl;
val[pre[i]] += mdl;
re += mdl * cst[pre[i] ^ 1];
}
}
return re;
} int A[110][110], id[110][110]; int main() {
int n = rd();
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= n; j ++ ) {
A[i][j] = rd();
}
}
int cnt = n;
for (int i = 1; i <= n; i ++ ) {
for (int j = i + 1; j <= n; j ++ ) {
if (A[i][j] == 2) {
cnt ++ ;
add(cnt, i, 1, 0);
id[i][j] = tot - 1;
add(cnt, j, 1, 0);
id[j][i] = tot - 1;
add(S, cnt, 1, 0);
}
}
}
// cout << tot << ' ' << cnt << endl ;
for (int i = 1; i <= n; i ++ ) {
int c = 0;
for (int j = 1; j <= n; j ++ ) {
if (A[i][j] == 1) {
c ++ ;
}
}
if (c) {
add(S, i, c, 0);
}
}
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= n; j ++ ) {
add(i, T, 1, j * (j - 1) / 2 - (j - 1) * (j - 2) / 2);
}
}
int ans = mincost();
ans = n * (n - 1) * (n - 2) / 6 - ans;
cout << ans << endl ;
for (int i = 1; i <= n; i ++ ) {
for (int j = 1; j <= n; j ++ ) {
if (A[i][j] != 2) {
printf("%d ", A[i][j]);
}
else {
if (i == j) {
printf("0 ");
}
else {
if (!val[id[i][j]]) {
printf("1 ");
}
else {
printf("0 ");
}
}
}
}
puts("");
}
return 0;
}
/*
6
0 2 1 0 2 1
2 0 0 2 2 2
0 1 0 2 1 1
1 2 2 0 1 2
2 2 0 0 0 2
0 2 0 2 2 0 */

小结:这个费用流很巧妙。就是有先后的选取过程,但是保证后面的代价比前面的代价大,我们可以暴力建边。

[bzoj2597][Wc2007]剪刀石头布_费用流的更多相关文章

  1. BZOJ2597 [Wc2007]剪刀石头布 【费用流】

    题目链接 BZOJ2597 题解 orz思维差 既然是一张竞赛图,我们选出任意三个点都可能成环 总方案数为 \[{n \choose 3}\] 如果三个点不成环,会发现它们的度数是确定的,入度分别为\ ...

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

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

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

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

  4. BZOJ_2661_[BeiJing wc2012]连连看_费用流

    BZOJ_2661_[BeiJing wc2012]连连看_费用流 Description 凡是考智商的题里面总会有这么一种消除游戏.不过现在面对的这关连连看可不是QQ游戏里那种考眼力的游戏.我们的规 ...

  5. BZOJ_1834_[ZJOI2010]network 网络扩容_费用流

    BZOJ_1834_[ZJOI2010]network 网络扩容_费用流 题意: 给定一张有向图,每条边都有一个容量C和一个扩容费用W.这里扩容费用是指将容量扩大1所需的费用. 求:  1.在不扩容的 ...

  6. BZOJ_1877_[SDOI2009]晨跑_费用流

    BZOJ_1877_[SDOI2009]晨跑_费用流 题意: Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他 坚持下来的只有晨跑. 现在给出 ...

  7. BZOJ_1070_[SCOI2007]修车_费用流

    BZOJ_1070_[SCOI2007]修车_费用流 Description 同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同 的车进行维修所用的时间 ...

  8. 【BZOJ-2597】剪刀石头布 最小费用最大流

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

  9. [WC2007]剪刀石头布(最大流)

    洛古 一句话题意:给定一张图,每两点之间有一条有向边或无向边,把所有无向边定向,使图中三元环个数尽量多 因为原图是一个完全图,假设图中任意三点都能构成三元环,那么途中三元环的个数为:\(\binom{ ...

随机推荐

  1. [转]vue解决刷新页面vuex数据、params参数消失的问题

    一般项目都会有一些逻辑需要传递值给另一个页面,那么有的时候就会出现一个问题:用户刷新了页面,诶?数据没了,参数错误.那么今天经过总结,解决了这个问题.我在最新的项目中,通过了一下几种情况进行传值: 1 ...

  2. Java数据库小项目01--实现用户登录注册

    先实现数据库和数据表,检测正常后再做其他的 CREATE TABLE users( username ) NOT NULL, PASSWORD ) NOT NULL); INSERT INTO use ...

  3. 在一个非默认的位置包含头文件stdafx.h

    如果stdafx.h和你当前的工程不在一个文件夹下,当你在代码中第一行写下#include "stdafx.h"时,VC编译器会根据编译规则(相关的规则请查看MSDN)来区别std ...

  4. shell中命令代换$()与`` 、 变量代换${} 、 整数运算$(( )) 的区别

    命令代换$()与`` . 变量代换${} . 整数运算$(( )) 1.$( ) 与 ` ` (反引号) 在 bash shell 中,$( ) 与 ` ` (反引号) 都是用来做命令替换用(comm ...

  5. [Linux]ubuntu更改国内源

    转自: https://blog.csdn.net/qq_35451572/article/details/79516563 推荐快速更新国内源 https://blog.csdn.net/qq_35 ...

  6. JAVA之工作线程数究竟要设置多少

    一.需求缘起 Web-Server通常有个配置,最大工作线程数,后端服务一般也有个配置,工作线程池的线程数量,这个线程数的配置不同的业务架构师有不同的经验值,有些业务设置为CPU核数的2倍,有些业务设 ...

  7. 解决Linux下Firefox无法启动的问题

    在linux下使用Firefox连接被测系统的GUI,一次偶然操作导致linux系统运行缓慢,Firefox无法正常操作,从system monitor 杀掉所有java进程将Firefox强行关闭. ...

  8. postgresql获取表最后更新时间(通过触发器将时间写入另外一张表)

    通过触发器方式获取表最后更新时间,并将时间信息写入到另外一张表 一.创建测试表和表记录更新时间表 CREATE TABLE weather( city varchar(80), temp_lo int ...

  9. phpstorm配置了git后Terminal 不能使用显示:git' 不是内部或外部命令,也不是可运行的程序

    问题:在phpstorm上配置好git后,将代码拉了下来 ,但是命令行无法使用显示如图 解决方法:①找到安装git的位置,然后在该目录的子目录下分别找到git-core.bin 两个目录,我的安装在了 ...

  10. Laravel 代码开发最佳实践

    我们这里要讨论的并不是 Laravel 版的 SOLID 原则(想要了解更多 SOLID 原则细节查看这篇文章)亦或是设计模式,而是 Laravel 实际开发中容易被忽略的最佳实践. 内容概览 单一职 ...