BZOJ

洛谷


\(Description\)

给定一张部分边方向已确定的竞赛图。你需要给剩下的边确定方向,使得图中的三元环数量最多。

\(n\leq100\)。


\(Solution\)

这种选择之间有影响,而且\(n\)很小的题考虑网络流啊。

最理想的情况能得到的三元环个数是\(C_n^3\)个。我们考虑怎样会使三元环个数减少。

如果三个点之间不成三元环,那么一定是某个点入度为\(2\),某个点出度为\(2\),另一个点入度出度都为\(1\)。

不妨只考虑入度。如果一个点入度为\(2\),那么会减少\(1\)个三元环;如果入度为\(3\),那么会减少\(C_3^2=3\)个三元环(设连向该点\(A\)的三个点为\(B,C,D\),\(A,B,C\)、\(A,B,D\)、\(A,C,D\)之间都形不成三元环)...

也就是设一个点的入度为\(dgr\),会减少\(C_{dgr}^2\)个三元环。那么答案就是\(C_n^3-\sum_{i=1}^nC_{dgr_i}^2\)。

而度数每次改变\(1\),减少的三元环个数是\(C_{dgr}^2-C_{dgr-1}^2=dgr-1\)。

然后就可以考虑给每个点分配度数了。对每条边新建一个点\(x\),由源点向\(x\)连容量\(1\)、费用\(0\)的边,\(x\)向边的两端点分别连容量为\(1\)、费用为\(0\)的边。

对于原图的\(n\)个点,每个点向汇点分别连容量为\(1\),费用为\(0,1,2,3...\)的边。

跑费用流,\(C_n^3-cost\)就是答案了。

实现上,对于确定的边并不需要建出来,把答案先减掉\(\frac{dgr_i(dgr_i-1)}{2}\);然后枚举\(i\)连向汇点的边时,费用从\(dgr_i\)开始枚举就可以了。(优化很明显)

数组memset(A,...,某个确定大小),注意A[]int还是boolbool是一字节!

另外有种随机化+迭代的做法,跑得很快:


SPFA:(日常被zkw吊打)

  1. //3032kb 3700ms
  2. #include <queue>
  3. #include <cstdio>
  4. #include <cctype>
  5. #include <cstring>
  6. #include <algorithm>
  7. //#define gc() getchar()
  8. #define MAXIN 300000
  9. #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
  10. typedef long long LL;
  11. const int N=105+105*52,M=4*105*105*2;
  12. int src,des,Enum,H[N],nxt[M],fr[M],to[M],cap[M],cost[M],pre[N];
  13. char IN[MAXIN],*SS=IN,*TT=IN;
  14. inline int read()
  15. {
  16. int now=0;register char c=gc();
  17. for(;!isdigit(c);c=gc());
  18. for(;isdigit(c);now=now*10+c-48,c=gc());
  19. return now;
  20. }
  21. inline void AE(int u,int v,int w,int c)
  22. {
  23. to[++Enum]=v, fr[Enum]=u, nxt[Enum]=H[u], H[u]=Enum, cap[Enum]=w, cost[Enum]=c;
  24. to[++Enum]=u, fr[Enum]=v, nxt[Enum]=H[v], H[v]=Enum, cap[Enum]=0, cost[Enum]=-c;
  25. }
  26. bool SPFA()
  27. {
  28. static int dis[N];
  29. static bool inq[N];
  30. static std::queue<int> q;
  31. memset(dis,0x3f,des+1<<2);
  32. dis[0]=0, q.push(0);
  33. while(!q.empty())
  34. {
  35. int x=q.front(); q.pop();
  36. inq[x]=0;
  37. for(int i=H[x],v; i; i=nxt[i])
  38. if(cap[i] && dis[v=to[i]]>dis[x]+cost[i])
  39. dis[v]=dis[x]+cost[i], pre[v]=i, !inq[v]&&(q.push(v),inq[v]=1);
  40. }
  41. return dis[des]<0x3f3f3f3f;
  42. }
  43. inline int Augment()
  44. {
  45. int res=0;
  46. for(int i=des; i; i=fr[pre[i]])
  47. res+=cost[pre[i]], --cap[pre[i]], ++cap[pre[i]^1];
  48. return res;
  49. }
  50. int MCMF()
  51. {
  52. int res=0;
  53. while(SPFA()) res+=Augment();
  54. return res;
  55. }
  56. int main()
  57. {
  58. static int dgr[105],id[N],tag[N],Ans[105][105];
  59. const int n=read(); Enum=1, src=0, des=(n*n+n)/2+1;
  60. if(n<3) return putchar('0'),0;
  61. for(int i=1,tot=n; i<=n; ++i)
  62. {
  63. for(int j=1; j<=i; ++j) read();
  64. for(int j=i+1; j<=n; ++j)
  65. switch(AE(0,++tot,1,0),read())
  66. {
  67. case 0: tag[tot]=1, ++dgr[j]; break;
  68. case 1: tag[tot]=2, ++dgr[i]; break;
  69. case 2: AE(tot,i,1,0), id[tot]=Enum, AE(tot,j,1,0); break;//->i: i wins
  70. }
  71. }
  72. int ans=n*(n-1)*(n-2)/6;
  73. for(int i=1; i<=n; ++i)
  74. {
  75. ans-=dgr[i]*(dgr[i]-1)/2;
  76. for(int j=dgr[i]; j<n-1; ++j) AE(i,des,1,j);
  77. }
  78. printf("%d\n",ans-MCMF());
  79. for(int i=1,tot=n; i<=n; ++i)
  80. for(int j=i+1; j<=n; ++j)
  81. if(tag[++tot]) Ans[i][j]=tag[tot]-1;
  82. else Ans[i][j]=cap[id[tot]]?1:0;
  83. for(int i=1; i<=n; ++i,putchar('\n'))
  84. {
  85. for(int j=1; j<i; ++j) printf("%d ",Ans[j][i]^1);
  86. for(int j=i; j<=n; ++j) printf("%d ",Ans[i][j]);
  87. }
  88. return 0;
  89. }

zkw:

  1. //2292kb 416ms
  2. #include <queue>
  3. #include <cstdio>
  4. #include <cctype>
  5. #include <cstring>
  6. #include <algorithm>
  7. //#define gc() getchar()
  8. #define MAXIN 300000
  9. #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
  10. typedef long long LL;
  11. const int N=105+105*52,M=4*105*105*2;
  12. int src,des,Cost,Enum,cur[N],H[N],nxt[M],fr[M],to[M],cap[M],cost[M],dis[N];
  13. bool vis[N];
  14. char IN[MAXIN],*SS=IN,*TT=IN;
  15. inline int read()
  16. {
  17. int now=0;register char c=gc();
  18. for(;!isdigit(c);c=gc());
  19. for(;isdigit(c);now=now*10+c-48,c=gc());
  20. return now;
  21. }
  22. inline void AE(int u,int v,int w,int c)
  23. {
  24. to[++Enum]=v, fr[Enum]=u, nxt[Enum]=H[u], H[u]=Enum, cap[Enum]=w, cost[Enum]=c;
  25. to[++Enum]=u, fr[Enum]=v, nxt[Enum]=H[v], H[v]=Enum, cap[Enum]=0, cost[Enum]=-c;
  26. }
  27. bool SPFA()
  28. {
  29. static bool inq[N];
  30. static std::queue<int> q;
  31. memset(dis,0x3f,des+1<<2);
  32. dis[0]=0, q.push(0);
  33. while(!q.empty())
  34. {
  35. int x=q.front(); q.pop();
  36. inq[x]=0;
  37. for(int i=H[x],v; i; i=nxt[i])
  38. if(cap[i] && dis[v=to[i]]>dis[x]+cost[i])
  39. dis[v]=dis[x]+cost[i], !inq[v]&&(q.push(v),inq[v]=1);
  40. }
  41. return dis[des]<0x3f3f3f3f;
  42. }
  43. int DFS(int x)
  44. {
  45. if(x==des) return 1;
  46. vis[x]=1;
  47. for(int &i=cur[x]; i; i=nxt[i])
  48. if(!vis[to[i]] && cap[i] && dis[to[i]]==dis[x]+cost[i] && DFS(to[i]))
  49. return --cap[i],++cap[i^1],Cost+=cost[i],1;
  50. return 0;
  51. }
  52. int MCMF()
  53. {
  54. while(SPFA())
  55. {
  56. memcpy(cur,H,des+1<<2), memset(vis,0,des+1);//bool是1字节!!!
  57. while(DFS(0));
  58. }
  59. return Cost;
  60. }
  61. int main()
  62. {
  63. static int dgr[105],id[N],tag[N],Ans[105][105];
  64. const int n=read(); Enum=1, src=0, des=(n*n+n)/2+1;
  65. if(n<3) return putchar('0'),0;
  66. for(int i=1,tot=n; i<=n; ++i)
  67. {
  68. for(int j=1; j<=i; ++j) read();
  69. for(int j=i+1; j<=n; ++j)
  70. switch(AE(0,++tot,1,0),read())
  71. {
  72. case 0: tag[tot]=1, ++dgr[j]; break;
  73. case 1: tag[tot]=2, ++dgr[i]; break;
  74. case 2: AE(tot,i,1,0), id[tot]=Enum, AE(tot,j,1,0); break;//->i: i wins
  75. }
  76. }
  77. int ans=n*(n-1)*(n-2)/6;
  78. for(int i=1; i<=n; ++i)
  79. {
  80. ans-=dgr[i]*(dgr[i]-1)/2;
  81. for(int j=dgr[i]; j<n-1; ++j) AE(i,des,1,j);
  82. }
  83. printf("%d\n",ans-MCMF());
  84. for(int i=1,tot=n; i<=n; ++i)
  85. for(int j=i+1; j<=n; ++j)
  86. if(tag[++tot]) Ans[i][j]=tag[tot]-1;
  87. else Ans[i][j]=cap[id[tot]]?1:0;
  88. for(int i=1; i<=n; ++i,putchar('\n'))
  89. {
  90. for(int j=1; j<i; ++j) printf("%d ",Ans[j][i]^1);
  91. for(int j=i; j<=n; ++j) printf("%d ",Ans[i][j]);
  92. }
  93. return 0;
  94. }

BZOJ.2597.[WC2007]剪刀石头布(费用流zkw)的更多相关文章

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

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

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

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

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

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

  4. [WC2007]剪刀石头布——费用流

    比较有思维含量的一道题 题意:给混合完全图定向(定向为竞赛图)使得有最多的三元环 三元环条件要求比较高,还不容易分开处理. 正难则反 考虑,什么情况下,三元组不是三元环 一定是一个点有2个入度,一个点 ...

  5. 2597: [Wc2007]剪刀石头布

    2597: [Wc2007]剪刀石头布 链接 分析: 费用流. 首先转化一下问题,整张图最优的情况是存在$C_n^3$个,即任意3个都行,然后考虑去掉最少不满足的三元环. 如果u赢了v,u向v连一条边 ...

  6. [模板] 网络流相关/最大流ISAP/费用流zkw

    最大流/ISAP 话说ISAP是真快...(大多数情况)吊打dinic,而且还好写... 大概思路就是: 在dinic的基础上, 动态修改层数, 如果终点层数 \(>\) 点数, break. ...

  7. [bzoj 1449] 球队收益(费用流)

    [bzoj 1449] 球队收益(费用流) Description Input Output 一个整数表示联盟里所有球队收益之和的最小值. Sample Input 3 3 1 0 2 1 1 1 1 ...

  8. BZOJ.5120.[清华集训2017]无限之环(费用流zkw 黑白染色)

    题目链接 LOJ 洛谷 容易想到最小费用最大流分配度数. 因为水管形态固定,每个点还是要拆成4个点,分别当前格子表示向上右下左方向. 然后能比较容易地得到每种状态向其它状态转移的费用(比如原向上的可以 ...

  9. CSU 1948: 超级管理员(普通费用流&&zkw费用流)

    Description 长者对小明施加了膜法,使得小明每天起床就像马丁的早晨一样. 今天小明早上醒来发现自己成了一位仓管员.仓库可以被描述为一个n × m的网格,在每个网格上有几个箱子(可能没有).为 ...

随机推荐

  1. kali linux宿主机和虚拟机互访实现方案

    1.攻防模拟中,将DVWA安装到自己的宿主机中,在kali Linux中通过sqlmap和其他工具启动嗅探攻击,需要配置网络.虚拟机采用桥接方式,并复制Mac地址状况. 2.查看各自系统下的IP地址. ...

  2. cf441 f组合数。。单调指针

    e没学过做不出来.. 处理合法的区间很麻烦,但是处理非合法的区间很容易 答案就是所有的取法-不合法的区间 这题一定要双边界推进处理!!!! 一开始用单边界向右推进,结果后来发现错了,拿样例1就可以证明 ...

  3. 充分认识Mysql

    使用开源产品是一种潮流.在使用之前,我们首先需要对Mysql 有一定的了解,特别是Mysql 的缺点.只有了解其缺点后,我们才知道,能不能真正的应用到我们的业务场景中去. 2.1 Mysql 数据库简 ...

  4. 饮冰三年-人工智能-Python-12之利其器pycharm

    1:下载.安装.与激活这里不再介绍了.需要注意的是激活时需要修改C:\Windows\System32\drivers\etc\hosts文件 2:工具使用 2.1 HelloWorld  File& ...

  5. meaven

    一个项目管理工具.java语言编写的,所以可以跨平台 https://mvnrepository.com/

  6. Django目录结构分析

    Django目录结构分析: Django的Linux项目目录记录 [root@cmdb Django]# tree mysite mysite ├── cmdb │   ├── admin.py # ...

  7. win10ssh连接ubuntu服务器并本地绘图

    update @ 2018-11-07 00:36:38 用xrdp+tigervnc等的组合,可以使用原生unity桌面.具体教程见ubuntu日常使用指南 工具准备 win10上: xshell, ...

  8. MySQL的预处理技术

    所谓的预处理技术,最初也是由MySQL提出的一种减轻服务器压力的一种技术! 传统mysql处理流程 1,  在客户端准备sql语句 2,  发送sql语句到MySQL服务器 3,  在MySQL服务器 ...

  9. H5利用pattern属性和oninvalid属性验证表单

    HTML代码 <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <ti ...

  10. [转]解决-Dmaven.multiModuleProjectDirectory system property is not set. Check $M2_HOME environment variable and mvn script match.

    来源:http://www.cnblogs.com/sprinng/p/5141233.html 1.添加M2_HOME的环境变量 2.Preference->Java->Installe ...