题目大概是说n个人两两进行比赛,问如何安排几场比赛的输赢使得A胜B,B胜C,C胜A这种剪刀石头布的三元组最多。

这题好神。

  • 首先,三元组总共有$C_n^3$个
  • 然后考虑最小化不满足剪刀石头布条件的三元组个数,而要求的结果就是总数-这个不满足的个数了:
    1. 对于三个人构不成剪刀石头布现象,当且仅当,其中一个人赢了其他两个人
    2. 而由于这是完全图,如果一个人赢了$x_i$场那么包含这个人且这个人赢的次数最多的不满足剪刀石头布现象的三元组就有$C_{x_i}^2$个
    3. 所以目的就是最小化$\sum C_{x_i}^2$,即$\sum x_i^2-C_n^2$,其中$C_n^2$是常数可以拿开
  • 考虑用最小费用最大流求解$\sum x_i^2$的最小值,源点-比赛-人-汇点这样连边:
    1. 源点到各个比赛的边是容量1费用0
    2. 比赛到人是容量1费用0的边
    3. 而人到汇点,根据那个目标式,可知如果流量是$f$,那么费用是$f^2$,解决的方式就是依次连接容量1费用分别是1、3、5、7、9……的边!
  • 构图完毕跑最小费用最大流,最多的剪刀石头布现象数就是$C_n^3-(MCMF-C_n^2)$,最后再遍历一下残量网络输出方案即可
 #include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define INF (1<<30)
#define MAXN 11111
#define MAXM 111111*4
struct Edge{
int u,v,cap,cost,next;
}edge[MAXM];
int vs,vt,NV,NE,head[MAXN];
void addEdge(int u,int v,int cap,int cost){
edge[NE].u=u; edge[NE].v=v; edge[NE].cap=cap; edge[NE].cost=cost;
edge[NE].next=head[u]; head[u]=NE++;
edge[NE].u=v; edge[NE].v=u; edge[NE].cap=; edge[NE].cost=-cost;
edge[NE].next=head[v]; head[v]=NE++;
}
int d[MAXN],pre[MAXN];
bool vis[MAXN];
bool SPFA(){
for(int i=; i<NV; ++i){
d[i]=INF; vis[i]=;
}
d[vs]=; vis[vs]=;
queue<int> que;
que.push(vs);
while(!que.empty()){
int u=que.front(); que.pop();
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
if(edge[i].cap && d[v]>d[u]+edge[i].cost){
d[v]=d[u]+edge[i].cost;
pre[v]=i;
if(!vis[v]){
vis[v]=;
que.push(v);
}
}
}
vis[u]=;
}
return d[vt]!=INF;
}
int MCMF(){
int res=;
while(SPFA()){
int flow=INF,cost=;
for(int u=vt; u!=vs; u=edge[pre[u]].u){
flow=min(flow,edge[pre[u]].cap);
}
for(int u=vt; u!=vs; u=edge[pre[u]].u){
edge[pre[u]].cap-=flow;
edge[pre[u]^].cap+=flow;
cost+=flow*edge[pre[u]].cost;
}
res+=cost;
}
return res;
}
int ans[][];
int main(){
int n,a;
scanf("%d",&n);
vs=n*n+n; vt=vs+; NV=vt+; NE=;
memset(head,-,sizeof(head));
for(int i=; i<n; ++i){
int cost=;
for(int j=; j<=n; ++j){
addEdge(n*n+i,vt,,cost);
cost+=;
}
}
for(int i=; i<n; ++i){
for(int j=; j<n; ++j){
scanf("%d",&a);
if(i>=j) continue;
addEdge(vs,i*n+j,,);
if(a==){
addEdge(i*n+j,n*n+i,,);
}else if(a==){
addEdge(i*n+j,n*n+j,,);
}else{
addEdge(i*n+j,n*n+i,,);
addEdge(i*n+j,n*n+j,,);
}
}
}
printf("%d\n",n*(n-)*(n-)/-(MCMF()-(n-)*n/)/);
for(int x=; x<n; ++x){
for(int y=x+; y<n; ++y){
for(int i=head[x*n+y]; i!=-; i=edge[i].next){
if(i& || edge[i].cap) continue;
if(edge[i].v==x+n*n){
ans[x][y]=; ans[y][x]=;
}else{
ans[x][y]=; ans[y][x]=;
}
}
}
}
for(int i=; i<n; ++i){
for(int j=; j<n; ++j) printf("%d ",ans[i][j]);
putchar('\n');
}
return ;
}

BZOJ2597 [Wc2007]剪刀石头布(最小费用最大流)的更多相关文章

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

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

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

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

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

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

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

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

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

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

  6. [板子]最小费用最大流(Dijkstra增广)

    最小费用最大流板子,没有压行.利用重标号让边权非负,用Dijkstra进行增广,在理论和实际上都比SPFA增广快得多.教程略去.转载请随意. #include <cstdio> #incl ...

  7. bzoj1927最小费用最大流

    其实本来打算做最小费用最大流的题目前先来点模板题的,,,结果看到这道题二话不说(之前打太多了)敲了一个dinic,快写完了发现不对 我当时就这表情→   =_=你TM逗我 刚要删突然感觉dinic的模 ...

  8. ACM/ICPC 之 卡卡的矩阵旅行-最小费用最大流(可做模板)(POJ3422)

    将每个点拆分成原点A与伪点B,A->B有两条单向路(邻接表实现时需要建立一条反向的空边,并保证环路费用和为0),一条残留容量为1,费用为本身的负值(便于计算最短路),另一条残留容量+∞,费用为0 ...

  9. HDU5900 QSC and Master(区间DP + 最小费用最大流)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5900 Description Every school has some legends, ...

随机推荐

  1. October 11th 2016 Week 42nd Tuesday

    A friend is one who knows you and loves you just the same. 朋友就是懂你并爱你的人. Leave nothing for tomorrow w ...

  2. Redis 数据持久化(一)

    Redis的模块化开发设计的还是相当不错的,在Bio.h和Bio.c文件中定义了一个多线程的文件任务处理模块,在添加和处理任务的时候使用互斥锁和条件变量进行的同步,而且本身也支持多线程,这个模块的支持 ...

  3. Mysql之复制服务

    Replication[复制]使得数据可以从一个Master服务器上复制到一个或多个Slave上,默认是异步复制,不需要与Master建立永久连接:基于配置,可以作用于所有库,指定的库或库中的某些表. ...

  4. Destination Host Unreachable

    自己的Linux 机器连不上服务器了,ping XXXX的时候报这个错误了 看了一下是因为IP的原因==>进入Linux的图形界面==>System==>Administration ...

  5. Lattice 的 DDR IP核使用调试笔记之DDR 的 仿真

    —— 远航路上ing 整理于 博客园.转载请标明出处. 在上节建立完工程之后,要想明确DDR IP的使用细节,最好是做仿真.然后参考仿真来控制IP 核. 仿真的建立: 1.在IP核内的以下路径找到以下 ...

  6. 数据结构和算法 – 12.高级查找算法(下)

    哈希(散列)技术既是一种存储方法,也是一种查找方法.然而它与线性表.树.图等结构不同的是,前面几种结构,数据元素之间都存在某种逻辑关系,可以用连线图示表示出来,而哈希技术的记录之间不存在什么逻辑关系, ...

  7. CPU工作状态的知识介绍

    转自:http://www.bbwxbbs.com/forum.php?mod=viewthread&tid=2552   近几年,个人计算机的运行速度有了质的飞跃,但是功耗却没能与时俱进,着 ...

  8. C# 读取CSV文件

    CSV文件是用逗号作为分隔符的,所以如果是简单的CSV文件,用split(',')就可以了. 但是Excel 编辑CSV文件,且内容中有逗号,得到的csv文件如下:"aaa,aaa" ...

  9. Linux/centos下安装riak

    必备的组件: gccgcc-c++glibc-develmakepam-devel 使用yum安装相关组件 sudo yum install gcc gcc-c++ glibc-devel make ...

  10. JDK中的设计模式

    Creational(创建模式) Abstract factory: 创建一组有关联的对象实例.这个模式在JDK中也是相当的常见,还有很多的framework例如Spring.我们很容易找到这样的实例 ...