博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
bzoj2597: [Wc2007]剪刀石头布(费用流)
阅读量:5827 次
发布时间:2019-06-18

本文共 2689 字,大约阅读时间需要 8 分钟。

 

不得不说这思路真是太妙了

考虑能构成三元组很难,那我们考虑不能构成三元组的情况是怎么样

就是说一个三元组$(a,b,c)$,其中$a$赢两场,$b$赢一场,$c$没有赢

所以如果第$i$个人赢了$w_i$场,那么总共的不能构成的三元组就是$\sum_i{w_i*(w_i-1)}{2}$

最大化满足的数量,就是最小化不满足的数量,就是最小化上面那个式子

那么我们考虑构建网络流

建源汇

对第$i$个人,从它向汇点连容量为$n$的边

对于每一对$i,j$之间的比赛建一个点$C_{i,j}$,如果这场比赛尚未进行,那么源点向$C_{i,j}$连容$1$费$0$的边,$C_{i,j}向$i$和$j$连容$1$费$0$的边,表示这场比赛只能改变一个点的赢的场数

我们要最小化上式,那么我们考虑在费用上做文章

每个点$i$向汇点连边,但因为费用的增加是一次比一次大的,所以我们考虑把这条边拆成$n$条边,容量为$1$费用分别为$0,1,2...$

因为费用流每一次都先增广最小的费用,所以只要求出最小费用最大流即可

1 //minamoto 2 #include
3 #include
4 #include
5 #include
6 #define inf 0x3f3f3f3f 7 using namespace std; 8 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 9 char buf[1<<21],*p1=buf,*p2=buf;10 inline int read(){11 #define num ch-'0'12 char ch;bool flag=0;int res;13 while(!isdigit(ch=getc()))14 (ch=='-')&&(flag=true);15 for(res=num;isdigit(ch=getc());res=res*10+num);16 (flag)&&(res=-res);17 #undef num18 return res;19 }20 const int N=50005,M=100005;21 int head[N],Next[M],ver[M],edge[M],cost[M],tot=1;22 inline void add(int u,int v,int e,int c=0){23 ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e,cost[tot]=c;24 ver[++tot]=u,Next[tot]=head[v],head[v]=tot,edge[tot]=0,cost[tot]=-c;25 }26 int dis[N],vis[N],cur[N],S,T,ans;27 queue
q;28 bool spfa(){29 memset(dis,-1,sizeof(dis));30 memset(vis,0,sizeof(vis));31 memcpy(cur,head,sizeof(head));32 q.push(T),dis[T]=0,vis[T]=1;33 while(!q.empty()){34 int u=q.front();q.pop(),vis[u]=0;35 for(int i=head[u];i;i=Next[i])36 if(edge[i^1]){37 int v=ver[i],c=cost[i];38 if(dis[v]<0||dis[v]>dis[u]-c){39 dis[v]=dis[u]-c;40 if(!vis[v]) vis[v]=1,q.push(v);41 }42 }43 }44 return ~dis[S];45 }46 int dfs(int u,int limit){47 if(!limit||u==T) return limit;48 int flow=0,f;vis[u]=1;49 for(int i=cur[u];i;cur[u]=i=Next[i]){50 int v=ver[i];51 if(dis[v]==dis[u]-cost[i]&&!vis[v]&&(f=dfs(v,min(limit,edge[i])))){52 flow+=f,limit-=f;53 edge[i]-=f,edge[i^1]+=f;54 ans-=f*cost[i];55 if(!limit) break;56 }57 }58 vis[u]=0;59 return flow;60 }61 void zkw(){
while(spfa()) dfs(S,inf);}62 int mp[105][105],win[105][105],n,cnt;63 int main(){64 //freopen("testdata.in","r",stdin);65 n=read();66 for(int i=1;i<=n;++i)67 for(int j=1;j<=n;++j)68 mp[i][j]=read();69 S=0,cnt=n;70 for(int i=1;i<=n;++i)71 for(int j=1;j

 

转载于:https://www.cnblogs.com/bztMinamoto/p/9588354.html

你可能感兴趣的文章
P1382 楼房 set用法小结
查看>>
分类器性能度量
查看>>
Es学习第七课, term、terms、match等基本查询语法
查看>>
java 解析http返回xml数据
查看>>
windows 环境下切换 python2 与 pythone3 以及常用命令
查看>>
HashMap和Hashtable的差别
查看>>
ASP.NET Core学习网站推荐
查看>>
FIDDLER的使用方法及技巧总结[连载2]---FIDDLER用户界面
查看>>
java连接MySQL数据库操作步骤
查看>>
Node.js 从入门到茫然系列——入门篇
查看>>
武汉科技大学ACM :1006: A+B for Input-Output Practice (VI)
查看>>
如何判断主机是大端还是小端(字节序)
查看>>
MySQL用命令行导出数据库
查看>>
docker 基础
查看>>
C++中STRING转为INT (转)
查看>>
ASP.NET上传多个文件
查看>>
学习:UTF-8和GBK的区别
查看>>
Shape parameter 形状参数
查看>>
【求助】小系统组成大系统所遇到的问题
查看>>
js 中英文字符串长度
查看>>