【BZOJ2597】[Wc2007]剪刀石头布 最小费用流
【BZOJ2597】[Wc2007]剪刀石头布
Description
Input
Output
Sample Input
0 1 2
0 0 2
2 2 0
Sample Output
0 1 0
0 0 1
1 0 0
HINT
100%的数据中,N≤ 100。
题解:看到数据范围和大致题意想到了网络流(并且是拆边的那种),然后正着做不出来想到反着做,然而自己太弱了反着做都做不出来,于是看大爷的题解,秒懂。
为了建图,首先我们想象原图是一张竞赛图(任意两点之间有一条有向边相连),我们要给部分边定向,使得形成的三元环尽可能多。我们考虑每个三元组,如果不能形成环,当且仅当一个点的出度=2。所以,一个点的每两个出度就对应了失去的一个三元环。所以总环数=$C_n^3-\sum C_{d[i]}^2$。然后$C_{d[i]}^2={d[i]*(d[i]-1)\over 2}$,差分一下就会发现一个点每次d[i]++,就要失去d[i]-1个三元环。所以我们想到以出度为流量,构建最小费用最大流模型。
建图部分其实很简单,不具体解释了,直接上连边方法:
1.S->每条无向边 费用0,容量1
2.每条无向边->它的两个顶点 费用0,容量1
3.每个点->T 连若干条边,其中第i条费用i-1,容量1
至于原图中的有向边,特判一下就好了。输出方案什么的,自己搞一搞吧~
- #include <cstdio>
- #include <cstring>
- #include <iostream>
- #include <queue>
- using namespace std;
- int n,cnt,S,T,tot,ans;
- int to[1000000],next[1000000],cost[1000000],flow[1000000],dis[10000],inq[10000],pe[10000],pv[10000],head[10000];
- int d[110],res[110][110];
- queue<int> q;
- int rd()
- {
- int ret=0,f=1; char gc=getchar();
- while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
- while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
- return ret*f;
- }
- void add(int a,int b,int c,int d)
- {
- to[cnt]=b,cost[cnt]=c,flow[cnt]=d,next[cnt]=head[a],head[a]=cnt++;
- to[cnt]=a,cost[cnt]=-c,flow[cnt]=0,next[cnt]=head[b],head[b]=cnt++;
- }
- int bfs()
- {
- memset(dis,0x3f,sizeof(dis));
- int i,u;
- q.push(S),dis[S]=0;
- while(!q.empty())
- {
- u=q.front(),q.pop(),inq[u]=0;
- for(int i=head[u];i!=-1;i=next[i])
- {
- if(dis[to[i]]>dis[u]+cost[i]&&flow[i])
- {
- dis[to[i]]=dis[u]+cost[i],pe[to[i]]=i,pv[to[i]]=u;
- if(!inq[to[i]]) inq[to[i]]=1,q.push(to[i]);
- }
- }
- }
- return dis[T]<0x3f3f3f3f;
- }
- int main()
- {
- n=rd(),S=0,T=tot=n+1;
- int i,j,a,mf;
- memset(head,-1,sizeof(head));
- for(i=1;i<=n;i++)
- {
- for(j=1;j<=n;j++)
- {
- a=rd();
- if(i>=j) continue;
- if(a==2) res[i][j]=cnt+3,add(S,++tot,0,1),add(tot,i,0,1),add(tot,j,0,1),add(i,T,d[i]++,1),add(j,T,d[j]++,1);
- if(a==1) res[i][j]=-1,add(S,i,0,1),add(i,T,d[i]++,1);
- if(a==0) res[i][j]=-2,add(S,j,0,1),add(j,T,d[j]++,1);
- }
- }
- ans=n*(n-1)*(n-2)/6;
- while(bfs())
- {
- mf=1<<30;
- for(i=T;i!=S;i=pv[i]) mf=min(mf,flow[pe[i]]);
- ans-=dis[T]*mf;
- for(i=T;i!=S;i=pv[i]) flow[pe[i]]-=mf,flow[pe[i]^1]+=mf;
- }
- printf("%d\n",ans);
- for(i=1;i<=n;i++)
- {
- for(j=1;j<=n;j++)
- {
- if(j!=1) printf(" ");
- if(i>j) printf("%d",res[j][i]^1);
- else if(i==j) printf("0");
- else
- {
- if(res[i][j]==-1) res[i][j]=1;
- else if(res[i][j]==-2) res[i][j]=0;
- else res[i][j]=flow[res[i][j]];
- printf("%d",res[i][j]);
- }
- }
- printf("\n");
- }
- return 0;
- }
【BZOJ2597】[Wc2007]剪刀石头布 最小费用流的更多相关文章
- [bzoj2597][Wc2007]剪刀石头布_费用流
[Wc2007]剪刀石头布 题目大意:https://www.lydsy.com/JudgeOnline/problem.php?id=2597 题解: 发现直接求三元环不好求,我们考虑任选三个点不是 ...
- BZOJ2597 WC2007剪刀石头布(费用流)
考虑使非剪刀石头布情况尽量少.设第i个人赢了xi场,那么以i作为赢家的非剪刀石头布情况就为xi(xi-1)/2种.那么使Σxi(xi-1)/2尽量小即可. 考虑网络流.将比赛建成一排点,人建成一排点, ...
- BZOJ2597 [Wc2007]剪刀石头布(最小费用最大流)
题目大概是说n个人两两进行比赛,问如何安排几场比赛的输赢使得A胜B,B胜C,C胜A这种剪刀石头布的三元组最多. 这题好神. 首先,三元组总共有$C_n^3$个 然后考虑最小化不满足剪刀石头布条件的三元 ...
- bzoj2597: [Wc2007]剪刀石头布
Description 在一些一对一游戏的比赛(如下棋.乒乓球和羽毛球的单打)中,我们经常会遇到A胜过B,B胜过C而C又胜过A的有趣情况,不妨形象的称之为剪刀石头布情况.有的时候,无聊的人们会津津乐道 ...
- BZOJ2597 [Wc2007]剪刀石头布 【费用流】
题目链接 BZOJ2597 题解 orz思维差 既然是一张竞赛图,我们选出任意三个点都可能成环 总方案数为 \[{n \choose 3}\] 如果三个点不成环,会发现它们的度数是确定的,入度分别为\ ...
- bzoj2597: [Wc2007]剪刀石头布(费用流)
传送门 不得不说这思路真是太妙了 考虑能构成三元组很难,那我们考虑不能构成三元组的情况是怎么样 就是说一个三元组$(a,b,c)$,其中$a$赢两场,$b$赢一场,$c$没有赢 所以如果第$i$个人赢 ...
- 【BZOJ-2597】剪刀石头布 最小费用最大流
2597: [Wc2007]剪刀石头布 Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 1016 Solved: ...
- [Wc2007]剪刀石头布
[Wc2007]剪刀石头布 http://www.lydsy.com/JudgeOnline/problem.php?id=2597 Time Limit: 20 Sec Memory Limit: ...
- 2597: [Wc2007]剪刀石头布
2597: [Wc2007]剪刀石头布 链接 分析: 费用流. 首先转化一下问题,整张图最优的情况是存在$C_n^3$个,即任意3个都行,然后考虑去掉最少不满足的三元环. 如果u赢了v,u向v连一条边 ...
随机推荐
- Action 和 Func 的用法以及区别
Action 无返回值 Func 有返回值,且最后一个参数为返回值 Action用法 public static void test(string s) { Console.WriteLine(&qu ...
- Axisfault faultcode:Server.userException异常
---恢复内容开始--- Axisfault faultcode:Server.userException异常 AxisFault faultCode: {http://schemas.xmlsoap ...
- 通信API、使用Web Workers处理线程
1.跨文档消息传输 要想接受从其他的窗口那里发过来的消息,就必须对窗口对象的message事件进行监视. w ...
- mongodb培训
写在前面 公司组织的技术培训,虽然刚接触mongodb没多久,算是入门吧,就组织一次mongodb的入门ppt培训.包括nosql的简单介绍,以及mongodb的一些优缺点,最后包括mongodb的一 ...
- 【spring boot】8.spring boot的日志框架logback使用
在继续上一篇的Debug调试之后,把spring boot的日志框架使用情况逐步蚕食. 参考:http://tengj.top/2017/04/05/springbo 开篇之前,贴上完整applica ...
- centos使用yum安装gcc
yum -y install gccyum -y install gcc-c++yum install make -- 或者yum groupinstall "Development Too ...
- 通过Java的Domain类构建ElasticSearch的mapping
通过给定一个Java的class类自行创建ElasticSearch的mapping Order的domain类 public class Order { public String system_i ...
- spring Multiple MongoTemplate
<!-- 数据环境配置 --> <mongo:repositories base-package="com.my9yu.manager.module.server.repo ...
- Struts2 convention插件试用+ Spring+Hibernate SSH整合
第一步,引入struts2-convention-plugin-2.2.1.jar 然后,改动配置文件. 我是在struts.properties文件里改动的: struts.objectFactor ...
- Docker 开源管理工具集锦
俗话说工欲善其事.必先利其器.Docker 是一种详细的虚拟化技术,Docker 尽管以RestAPI形式提供服务.但在实际生产环境中,管理大规模集群部署的Docker容器确实是一个巨大的挑战.尽管D ...