题面:

  有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?)

  之后定向方案,看边对应的点哪条出边满流即可!

代码:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int N=,inf=0x3f3f3f3f;int f[N];
  4. struct node{int y,z,f,nxt;}e[N*];int lst[N];
  5. int n,S,T,tot,g[][],dg[N],tmp[N],X[N],Y[N];
  6. int h[N],c=,d[N],vis[N],pre[N],ans;queue<int>q;
  7. void add(int x,int y,int l,int z){
  8. e[++c]=(node){y,z,l,h[x]};h[x]=c;
  9. e[++c]=(node){x,-z,,h[y]};h[y]=c;
  10. } bool spfa(){
  11. for(int i=S;i<=T;i++) pre[i]=-,
  12. f[i]=inf,lst[i]=vis[i]=,d[i]=inf;
  13. q.push(S);d[S]=;pre[S]=;
  14. while(!q.empty()){
  15. int x=q.front();q.pop();vis[x]=;
  16. for(int i=h[x],y;~i;i=e[i].nxt)
  17. if(d[y=e[i].y]>d[x]+e[i].z&&e[i].f){
  18. d[y]=d[x]+e[i].z;pre[y]=x;lst[y]=i;
  19. f[y]=min(f[x],e[i].f);
  20. if(!vis[y]) vis[y]=,q.push(y);
  21. }
  22. } return pre[T]!=-;
  23. } void solve(){
  24. while(spfa()){
  25. ans+=d[T]*f[T];int x=T;
  26. while(x) e[lst[x]].f-=f[T],
  27. e[lst[x]^].f+=f[T],x=pre[x];
  28. } return ;
  29. } int main(){
  30. memset(h,-,sizeof(h));
  31. scanf("%d",&n);S=,tot=n;
  32. for(int i=;i<=n;i++)
  33. for(int j=;j<=n;j++){
  34. scanf("%d",&g[i][j]);
  35. if(g[i][j]==){
  36. if(i>j) continue;
  37. X[++tot]=i,Y[tot]=j;
  38. add(S,tot,,);
  39. add(tot,i,,);
  40. add(tot,j,,);
  41. tmp[i]++;tmp[j]++;
  42. } else dg[i]+=g[i][j];
  43. } T=++tot;for(int i=;i<=n;i++){
  44. ans+=(dg[i]*dg[i]-dg[i])/;
  45. for(int j=dg[i]+;j<n;j++)
  46. add(i,T,,j-);
  47. } solve();int tt=n*(n-)*(n-)/;
  48. printf("%d\n",tt-ans);
  49. for(int i=n+,v;i<tot;i++){
  50. for(int p=h[i];~p;p=e[p].nxt)
  51. if(e[p].y!=S&&!e[p].f)
  52. {v=e[p].y;break;}
  53. if(v==X[i]) g[X[i]][Y[i]]=,
  54. g[Y[i]][X[i]]=;
  55. else g[X[i]][Y[i]]=,g[Y[i]][X[i]]=;
  56. } for(int i=;i<=n;i++,puts(""))
  57. for(int j=;j<=n;j++)
  58. printf("%d ",g[i][j]);return ;
  59. }

费用流

WC2007 石头剪刀布 数学+最小费用最大流的更多相关文章

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

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

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

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

  3. HDU5988/nowcoder 207G - Coding Contest - [最小费用最大流]

    题目链接:https://www.nowcoder.com/acm/contest/207/G 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5988 ...

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

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

  5. bzoj1927最小费用最大流

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

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

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

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

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

  8. P3381 【模板】最小费用最大流

    P3381 [模板]最小费用最大流 题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行 ...

  9. 【BZOJ-3876】支线剧情 有上下界的网络流(有下界有源有汇最小费用最大流)

    3876: [Ahoi2014]支线剧情 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 821  Solved: 502[Submit][Status ...

随机推荐

  1. Ajax跨域访问等问题

    前端时间公司接口整顿,所有接口放一起了,然后我就写了一大堆API接口....... 今天用上了,公用人员库,前台通过ajax访问, 先是以‘json’作为数据格式进行访问,直接response fie ...

  2. Python科学计算工具包

    import numpy as np # 创建一个Ndarray # 1. 从list对象中创建 # 2. 创建一个特定的数组,全1数组ones,随机数组random.randn,对角矩阵diag # ...

  3. jvm学习理解

    1.本文是转载别人所写的,因为这个jvm看很多遍老是忘,转载只是备忘和查看方便. 转载地址: https://mp.weixin.qq.com/s/reFDCkUdq1QGGDs_Mnuesg 图中涉 ...

  4. 算法复习周------“动态规划之‘最长公共子序列’”&&《计蒜课》---最长公共子串题解

    问题描述: 这个问题其实很容易理解.就是给你两个序列X={x1,x2,x3......xm} Y={y1,y2,y3......ym},要求找出X和Y的一个最长的公共子序列. 例:Xi={A, B, ...

  5. [转]Boosting

    1 Boosting算法的起源 Boosting方法是一种用来提高弱分类算法准确度的方法,这种方法通过构造一个预测函数系列,然后以一定的方式将他们组合成一个预测函数.Boosting是一种提高任意给定 ...

  6. CodeFoces Round #443(div.2)

    http://codeforces.com/contest/879/ A. Borya's Diagnosis time limit per test 2 seconds memory limit p ...

  7. "HIBERNATE_SEQUENCE" does not exist问题处理

    JavaWeb应用在MySQL环境下可以正常运行,数据迁移至Oracle或者人大金仓后应用运行爆出如下错误: 严重: Servlet.service() for servlet [JeeCmsAdmi ...

  8. Matlab实现Butterworth滤波器 分类: 图像处理 2014-06-02 00:05 527人阅读 评论(0) 收藏

    下面是用Matlab实现的Butterworth高通.低通滤波器. clc;clear all;close all; I=imread('cameraman.tif'); subplot(3,2,1) ...

  9. Oracle报错:"ORA-18008: 无法找到 OUTLN 方案 "的解决方案

    Oracle报错:"ORA-18008: 无法找到 OUTLN 方案 "的解决方案     今天连接到Oracle报错:ORA-18008: 无法找到 OUTLN 方案,前天还用得 ...

  10. 获取select里面option所有的值

    1.HTML结构 <select id="test"> <option value="option-1">option-1</op ...