2597: [Wc2007]剪刀石头布

链接

分析:  

  费用流。

  首先转化一下问题,整张图最优的情况是存在$C_n^3$个,即任意3个都行,然后考虑去掉最少不满足的三元环。

  如果u赢了v,u向v连一条边,如果v有k条入边,那么说明少了$C_k^2$个三元环,所对每场比赛分配度数,求最小费用最大流。

  具体地:S向每场比赛连容量为1,花费为0的边;每场比赛向两个人连容量为1,花费为0的边;每个人因为度数不同,花费不同,所以差分后建边。

  还有一种随机化+迭代的做法。

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = , INF = 1e9;
struct Edge { int from, to, nxt, cap, cost; } e[];
int head[N], pre[N], dis[N], q[], deg[N], id[][], A[][], P[N], tag[N], En = , S, T;
bool vis[N]; inline void add_edge(int u,int v,int f,int w) {
++En; e[En].from = u, e[En].to = v, e[En].cap = f, e[En].cost = w, e[En].nxt = head[u]; head[u] = En;
++En; e[En].from = v, e[En].to = u, e[En].cap = , e[En].cost = -w, e[En].nxt = head[v]; head[v] = En;
}
bool spfa() {
for (int i = ; i <= T; ++i) dis[i] = INF, vis[i] = false, pre[i] = ;
int L = , R = ;
q[++R] = S, vis[S] = true, dis[S] = ;
while (L <= R) {
int u = q[L ++]; vis[u] = false;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (dis[v] > dis[u] + e[i].cost && e[i].cap > ) {
dis[v] = dis[u] + e[i].cost;
pre[v] = i;
if (!vis[v]) q[++R] = v, vis[v] = true;
}
}
}
return dis[T] != INF;
}
int mcf() {
int Cost = , Flow = ;
while (spfa()) {
int now = 1e9;
for (int i = T; i != S; i = e[pre[i]].from)
now = min(now, e[pre[i]].cap);
for (int i = T; i != S; i = e[pre[i]].from)
e[pre[i]].cap -= now, e[pre[i] ^ ].cap += now;
Cost += dis[T] * now;
Flow += now;
}
return Cost;
}
int main() {
freopen("a.in", "r", stdin);
int n = read(), tot = n;
if (n < ) { printf(""); return ; }
for (int i = ; i <= n; ++i) {
for (int j = ; j <= i; ++j) read();
for (int j = i + ; j <= n; ++j) {
int x = read();
id[i][j] = ++tot;
if (x == ) deg[j] ++, tag[tot] = ;
else if (x == ) deg[i] ++, tag[tot] = ;
else { add_edge(tot, i, , ); P[tot] = En; add_edge(tot, j, , ); }
}
}
S = , T = tot + ;
for (int i = n + ; i <= tot; ++i) add_edge(S, i, , );
for (int i = ; i <= n; ++i)
for (int j = deg[i]; j < n - ; ++j) add_edge(i, T, , j);
int ans = n * (n - ) * (n - ) / ;
for (int i = ; i <= n; ++i)
ans -= deg[i] * (deg[i] - ) / ;
ans -= mcf();
printf("%d\n", ans);
for (int i = ; i <= n; ++i)
for (int j = i + ; j <= n; ++j) {
if (tag[id[i][j]]) A[i][j] = tag[id[i][j]] - ;
else A[i][j] = e[P[id[i][j]]].cap ? : ;
}
for (int i = ; i <= n; ++i, puts("")) {
for (int j = ; j < i; ++j) printf("%d ", A[j][i] ^ );
for (int j = i; j <= n; ++j) printf("%d ", A[i][j]);
}
return ;
}

2597: [Wc2007]剪刀石头布的更多相关文章

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

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

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

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

  3. bzoj 2597: [Wc2007]剪刀石头布【最小费用最大流】

    脑子不太清楚一个zz问题调了好久-- 首先正难则反,因为三元环好像没什么特点,就考虑让非三元环个数最小 考虑非三元环特点,就是环上一定有一个点的入度为2,联系整张图,三元环个数就是每个点C(入度,2) ...

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

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

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

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

  6. [Wc2007]剪刀石头布

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

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

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

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

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

  9. 【bzoj 2597】[Wc2007]剪刀石头布(图论--网络流 最小费用最大流)

    题目:在一些一对一游戏的比赛(如下棋.乒乓球和羽毛球的单打)中,我们经常会遇到A胜过B,B胜过C而C又胜过A的有趣情况,不妨形象的称之为剪刀石头布情况.有的时候,无聊的人们会津津乐道于统计有多少这样的 ...

随机推荐

  1. Linux man 命令详细介绍

    知道linux帮助文件(man-pages,手册页)一般放在,$MANPATH/man 目录下面,而且按照领域与语言放到不同的目录里面. 看了上一章,要找那个命令使用相关手册,只要我们按照领域区分,到 ...

  2. linux下yum安装指定的mysql版本

    因为直接使用yum安装的mysql会是默认版本5.1的版本  但是有的同学不满足又想要其他版本的怎么办呢? 曾时候我来提供一种方案(仅供参考): 我们可以使用rpm包来进行指定mysql版本的安装, ...

  3. [翻译] UPCardsCarousel

    UPCardsCarousel UPCardsCarousel is a carousel with a cards based UI for iOS. UPCardsCarousel是一个旋转木马效 ...

  4. 2018年阿里巴巴关于java重要开源项目汇总

    1.分布式应用服务开发的一站式解决方案 Spring Cloud Alibaba Spring Cloud Alibaba 致力于提供分布式应用服务开发的一站式解决方案.此项目包含开发分布式应用服务的 ...

  5. Python学习---Django拾遗180328

    Django之生命周期 前台发送URL请求到Django的中间件进行内容校验,完成校验后到达路由映射文件url.py,然后调用视图函数views.py里面的函数进行内容处理[ 1.操作数据库进行数据读 ...

  6. Python学习---Form拾遗180322

    Form操作之错误信息操作 1. 用户发送请求过来 2. for 循环对字段进行正则表达式的验证  fields.clean(value) 3. 自定义clean_字段() 进行名字段值正确性的校验 ...

  7. CMake: Could NOT find PkgConfig

    转自http://www.ogre3d.org/forums/viewtopic.php?f=22&t=78490 Looking for OGRE... Could NOT find Pkg ...

  8. docker及服务器遇到的坑

    目录 DNS不可用 修改docker查找源 容器保持固定ip 查看docker连接 容器间通信 容器拷贝数据 php连接docker mysql 8.0出错authentication method ...

  9. Hadoop HBase概念学习系列之行、行键(十一)

    行是由列簇中的列组成.行根据行键依照字典顺序排序. HBase的行使用行键标识,可以使用行键查询整行的数据. 对同一个行键的访问都会落在同样的物理节点上.如果表包含2个列簇,属于两个列簇的文件还是保存 ...

  10. 复用$.ajax方式传递参数错误处理

    1.封装后的方法,在 data:inData 传递参数的方式和一般不一样,如果不注意会出现错误. function getDataByJsonP(methName, inData, fn) { $.a ...