WC2007 石头剪刀布 数学+最小费用最大流
题面:
有N个人参加一场比赛,赛程规定任意两个人之间都要进行一场比赛:这样总共有N*(N-1)/2场比赛。比赛已经进行了一部分,我们想知道在极端情况下,比赛结束后最多会发生多少剪刀石头布情况。即给出已经发生的比赛结果,而你可以任意安排剩下的比赛的结果,以得到尽量多的剪刀石头布情况。
剪刀石头布情况,即无序三元组(A, B, C),满足其中的一个人在比赛中赢了另一个人,另一个人赢了第三个人而第三个人又胜过了第一个人。
分析:
把题意转化一下,就是给定了一张有向完全图的残本,剩下的边你可以任意安排,求出现最多的三元环数量。
我们可以用一下小小的容斥,假如我们任选三个点,方案数是C(n,3),我们就找出最少失去的三元环数量,就可以给出这个题的答案了。
根据《一眼看出法》,我们可以了解,假如一个点x的入度(以下简称in[x])为w,那么它会使整个图失去的三元环数量为C(w,2)。
即:如果一个点的入度增加1,会使三元环数量减少in[x]-1这么多。所以我们需要尽量保证不会出现某个点入度特别多,换句话说就是尽量让入度平均。(这大概就是题解中说的凸函数的性质???)
所以,我们将失去的三元环作费用,跑费用流。
对于未定向的边,我们将其抽象成点(这里原图中的点也被抽象成点)
我们由源点S向每条未定向的边对应的点连边,容量为1费用为0;
对于每条被我们建成点的边,我们从这个点向这条边连通的两个点连边,容量为1,费用为0,表示这条边会给其中一个点带来入度加一的贡献。
对于每个原图上的节点x,我们想汇点T连接若干条边,容量都为1,费用分别为in[x], in[x]+1, in[x]+2,…,n-2(表示每增加1个单位的流量,就会带来这么多三元环的毁灭。想想为什么最大是n-2?)
之后定向方案,看边对应的点哪条出边满流即可!
代码:
#include<bits/stdc++.h>
using namespace std;
const int N=,inf=0x3f3f3f3f;int f[N];
struct node{int y,z,f,nxt;}e[N*];int lst[N];
int n,S,T,tot,g[][],dg[N],tmp[N],X[N],Y[N];
int h[N],c=,d[N],vis[N],pre[N],ans;queue<int>q;
void add(int x,int y,int l,int z){
e[++c]=(node){y,z,l,h[x]};h[x]=c;
e[++c]=(node){x,-z,,h[y]};h[y]=c;
} bool spfa(){
for(int i=S;i<=T;i++) pre[i]=-,
f[i]=inf,lst[i]=vis[i]=,d[i]=inf;
q.push(S);d[S]=;pre[S]=;
while(!q.empty()){
int x=q.front();q.pop();vis[x]=;
for(int i=h[x],y;~i;i=e[i].nxt)
if(d[y=e[i].y]>d[x]+e[i].z&&e[i].f){
d[y]=d[x]+e[i].z;pre[y]=x;lst[y]=i;
f[y]=min(f[x],e[i].f);
if(!vis[y]) vis[y]=,q.push(y);
}
} return pre[T]!=-;
} void solve(){
while(spfa()){
ans+=d[T]*f[T];int x=T;
while(x) e[lst[x]].f-=f[T],
e[lst[x]^].f+=f[T],x=pre[x];
} return ;
} int main(){
memset(h,-,sizeof(h));
scanf("%d",&n);S=,tot=n;
for(int i=;i<=n;i++)
for(int j=;j<=n;j++){
scanf("%d",&g[i][j]);
if(g[i][j]==){
if(i>j) continue;
X[++tot]=i,Y[tot]=j;
add(S,tot,,);
add(tot,i,,);
add(tot,j,,);
tmp[i]++;tmp[j]++;
} else dg[i]+=g[i][j];
} T=++tot;for(int i=;i<=n;i++){
ans+=(dg[i]*dg[i]-dg[i])/;
for(int j=dg[i]+;j<n;j++)
add(i,T,,j-);
} solve();int tt=n*(n-)*(n-)/;
printf("%d\n",tt-ans);
for(int i=n+,v;i<tot;i++){
for(int p=h[i];~p;p=e[p].nxt)
if(e[p].y!=S&&!e[p].f)
{v=e[p].y;break;}
if(v==X[i]) g[X[i]][Y[i]]=,
g[Y[i]][X[i]]=;
else g[X[i]][Y[i]]=,g[Y[i]][X[i]]=;
} for(int i=;i<=n;i++,puts(""))
for(int j=;j<=n;j++)
printf("%d ",g[i][j]);return ;
}
费用流
WC2007 石头剪刀布 数学+最小费用最大流的更多相关文章
- BZOJ2597 [Wc2007]剪刀石头布(最小费用最大流)
题目大概是说n个人两两进行比赛,问如何安排几场比赛的输赢使得A胜B,B胜C,C胜A这种剪刀石头布的三元组最多. 这题好神. 首先,三元组总共有$C_n^3$个 然后考虑最小化不满足剪刀石头布条件的三元 ...
- bzoj 2597: [Wc2007]剪刀石头布【最小费用最大流】
脑子不太清楚一个zz问题调了好久-- 首先正难则反,因为三元环好像没什么特点,就考虑让非三元环个数最小 考虑非三元环特点,就是环上一定有一个点的入度为2,联系整张图,三元环个数就是每个点C(入度,2) ...
- HDU5988/nowcoder 207G - Coding Contest - [最小费用最大流]
题目链接:https://www.nowcoder.com/acm/contest/207/G 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5988 ...
- [板子]最小费用最大流(Dijkstra增广)
最小费用最大流板子,没有压行.利用重标号让边权非负,用Dijkstra进行增广,在理论和实际上都比SPFA增广快得多.教程略去.转载请随意. #include <cstdio> #incl ...
- bzoj1927最小费用最大流
其实本来打算做最小费用最大流的题目前先来点模板题的,,,结果看到这道题二话不说(之前打太多了)敲了一个dinic,快写完了发现不对 我当时就这表情→ =_=你TM逗我 刚要删突然感觉dinic的模 ...
- ACM/ICPC 之 卡卡的矩阵旅行-最小费用最大流(可做模板)(POJ3422)
将每个点拆分成原点A与伪点B,A->B有两条单向路(邻接表实现时需要建立一条反向的空边,并保证环路费用和为0),一条残留容量为1,费用为本身的负值(便于计算最短路),另一条残留容量+∞,费用为0 ...
- HDU5900 QSC and Master(区间DP + 最小费用最大流)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5900 Description Every school has some legends, ...
- P3381 【模板】最小费用最大流
P3381 [模板]最小费用最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行 ...
- 【BZOJ-3876】支线剧情 有上下界的网络流(有下界有源有汇最小费用最大流)
3876: [Ahoi2014]支线剧情 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 821 Solved: 502[Submit][Status ...
随机推荐
- 通过struts2-spring-plugin集成Struts2和Spring,报错:ClassNotFound:*Interceptor.......
集成Struts2和Spring的时候,出现错误,ClassNotFound: *interceptor,之所以是*interceptor是因为报了好多个这样的错误,而且类名都不一样. 集成方法是通过 ...
- 查询及删除重复记录的SQL语句
1.查找表中多余的重复记录,重复记录是根据单个字段(peopleId)来判断 select * from people where peopleId in (select peopleId from ...
- windows下 zookeeper dubbo 安装+配置+demo 详细图文教程
Java集群优化——dubbo+zookeeper构建 互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,Dubbo是一个分布式服务框架,在这 ...
- eclipse本地怎么和git相同
1.打开Eclipse后,在左侧的项目窗口空白处右键,选择“Import...”2.打开Import窗口后,选择“Git”->"Projects from Git",点击“N ...
- 前缀和小结 By cellur925
这篇主要是来介绍前缀和的QAQ. 前缀和有一维的和二维的,一维的很容易理解,高中数学必修5第二章数列给出了前n项和的概念,就是前缀和.一维的我们在这里简单说一句. 一维前缀和 预处理:在输入一个数列的 ...
- Python实现判断回文串
回文数的概念:即是给定一个数,这个数顺读和逆读都是一样的.例如:121,1221,a,aa是回文数,123,1231不是回文数. while 1: String = input('请先输入一个字符串 ...
- 简单备份11g db (文件系统)
1.more check.sqlsqlplus / as sysdba << EOF!banner start dbstartupselect name from v\$database; ...
- mysqlshow(数据库对象查看工具)
mysqlshow是mysql客户端对象查看工具,可以用来查看数据库.数据库中的表.表中的列.索引等. 1.mysqlshow命令的语法 shell > mysqlshow [options] ...
- 【图片匹配】--- SIFT_Opencv3.1.0_C++_ubuntu
最近在捣鼓图片相似性匹配算法.这里先说一点必要的题外话: 如果是在同一个object不同角度拍摄的多张图片中,使用SIFT可以有不错的效果: 如果是寻找类别相同的图片(可能不是同一object),SI ...
- POJ 2002 Squares 数学 + 必须hash
http://poj.org/problem?id=2002 只能说hash比二分快很多.随便一个hash函数都可以完爆二分. 判断是否存在正方形思路如下: 1.枚举任意两个点,作为正方形的一条边,那 ...