Codeforces Educational Round#21 F(808F) Solution:网络流(最小割)
来源:互联网 发布:软件开发咨询 编辑:程序博客网 时间:2024/05/23 15:06
题意:给出一组卡牌(100张),卡牌有三个属性值:power,c,level,其中c和level是用来限制的,power是目标值。
具体的限制规则是:只有level小于等于玩家的playerlevel的卡牌才可以使用,任意两张c之和为prime的卡牌不能同时使用。
求出一个人物的最小等级,使得可以找到一个方案使得选用的卡牌的power值累计大于等于k。
这个题很容易想到二分playerlevel,然后关键在于已知playerlevel的时候,如何计算可以得到的最大的power。
Solution是使用maxFlow,这算是一个网络流建图题。
首先可以预处理出所有相互冲突的卡牌。如果在他们之间连接一条边,就构成了一个冲突网络。显而易见:一条边的两个端点一定是一个奇数一个偶数。
那么可以把节点归为偶数的点和奇数的点。现在的问题是,要去掉一些点,使得网络为空。下面讲解建图技巧。
构造一个偶数超源102点,一个奇数超汇101点,102点会和每一个偶数点连一条指向偶数点的边,边的容量是偶数点的power,101点会和每个技术点连一条指向101点的边,容量为奇数点的power。然后再冲突的奇偶点之间连接从偶数点指向奇数点的边,容量是INF。建图完成。
那么首先这张初始图上的总power值就是各个奇偶点的power之和,然后下面开始“去掉一些点,使得不存在冲突关系”。
从101到102跑一次maxFlow可以得到这个冲突网络的最大流,也就是最小割。那么考虑这个最小割的实际意义:划定一个边集,这个边集可以将冲突网络分成不想连的两部分,且我这个边集的边权之和最小,那么显然,我们的那些冲突边不可能出现在这里边, 因为他们都是INF,因此,显而易见,这个最小割当然就是我们要得到的答案。因为割掉这些边之后,我们就不存在一条经过102-偶数点-冲突边-奇数点-101的流了,也就是说,要么奇数点-101的边被割了,要么偶数点-102的边被割了,要么同时被割了(可能存在多重冲突情况,需要两个点都割),这样就能保证网络变得合法而不冲突,而且最小割也保证了这是代价最小的割,因此就是我们要的答案。
格外要注意1的情形,1虽然属于奇数点,但是考虑出现多个1的时候,这些1都是“奇数”,但是任意两个1之间也存在冲突关系,但是上面我们只考虑了从超源102-超汇101之间要没有带冲突的流,而没有考虑1-1之间这个冲突边,所以不能同时出现多个1在我们的图中,这个也很好处理,显然,在我们的卡组中,至多会有一张c=1的牌,所以建图的时候,先遍历一次得到我可以使用的power最大的那个c=1的牌,而把剩下其他的c=1的牌都舍弃掉就可以了。
注:dinic不需要反向弧
AC代码(需要改动):
#include<bits/stdc++.h>using namespace std;#define MAXN 105#define MAXM 100005int first[MAXN],nxt[MAXM],dis[MAXM],cont[MAXM];int m,n,k,s,t,tot;int p[MAXN],c[MAXN],l[MAXN];bool prm[200005];int deep[MAXN];int que[MAXN*10];bool hasEdge[MAXN][MAXN];int maxone=-1;int maxoneindex=-1;bool bfs(){ int l=0,r=1; que[1]=s; memset(deep,0,sizeof(deep)); while (l<r){ l++; int q = que[l]; int tt=first[q]; while (tt!=-1){ if (dis[tt]!=s&&cont[tt]>0&&deep[dis[tt]]==0){ deep[dis[tt]]=deep[q]+1; r++; que[r]=dis[tt]; } tt=nxt[tt]; } } if (deep[t]==0){ return false; }else{ return true; }}int dfs(int now,int limit){ if (now==t||limit==0){ return limit; } if (limit<=0){ return 0; } int flow=0,f; int tt=first[now]; while (tt!=-1){ if (deep[dis[tt]]-deep[now]==1){ int temp = dfs(dis[tt],min(limit,cont[tt])); cont[tt]-=temp; cont[tt^1]+=temp; limit-=temp; flow+=temp; if (limit==0){ break; } } tt=nxt[tt]; } return flow;}int maxFlow(int least){ tot=-1; for (int i=0;i<103;i++){ first[i]=-1; } for (int i=0;i<n;i++){ for (int j=i+1;j<n;j++){ if (c[i]==1&&i!=maxoneindex){ continue; } if (c[j]==1&&j!=maxoneindex){ continue; } if (hasEdge[i][j]&&l[i]<=least&&l[j]<=least){ int ii,jj; if (c[i]&1){ ii=i; jj=j; }else{ ii=j; jj=i; } tot++; cont[tot]=2147483647; dis[tot]=jj; nxt[tot]=first[ii]; first[ii]=tot; tot++; cont[tot]=0; dis[tot]=ii; nxt[tot]=first[jj]; first[jj]=tot; } } } int sum =0; for (int i=0;i<n;i++){ if (c[i]==1&&i!=maxoneindex){ continue; } if (l[i]<=least){ sum+=p[i]; if (c[i]&1){ tot++; cont[tot]=p[i]; dis[tot]=i; nxt[tot]=first[101]; first[101]=tot; tot++; cont[tot]=p[i]; dis[tot]=101; nxt[tot]=first[i]; first[i]=tot; }else{ tot++; cont[tot]=p[i]; dis[tot]=i; nxt[tot]=first[102]; first[102]=tot; tot++; cont[tot]=p[i]; dis[tot]=102; nxt[tot]=first[i]; first[i]=tot; } } } int ans =0; while (bfs()){ ans+=dfs(s,2147483647); } return sum-ans;} int main(){ memset(prm,true,sizeof(prm)); prm[0]=prm[1]=false; for (int i=2;i<200000;i++){ if (prm[i]){ int tmp=i<<1; while (tmp<200000){ prm[tmp]=false; tmp+=i; } } } cin>>n>>k; memset(hasEdge,false,sizeof(hasEdge)); for (int i=0;i<n;i++){ cin>>p[i]>>c[i]>>l[i]; if (c[i]==1&&p[i]>maxone){ maxone=p[i]; maxoneindex=i; } for (int j=0;j<i;j++){ if (prm[c[i]+c[j]]){ hasEdge[i][j]=hasEdge[j][i]=true; } } } s=101; t=102; if (maxFlow(101)<k){ cout<<"-1"<<endl; return 0; } int l=0; int r=101; while (r-l>1){ int mid =(l+r)>>1; if (maxFlow(mid)>=k){ r=mid; }else{ l=mid; } } if (maxFlow(l)>=k){ cout<<l<<endl; }else{ cout<<r<<endl; } return 0;}
- Codeforces Educational Round#21 F(808F) Solution:网络流(最小割)
- Codeforces 808F 网络流最小割(二分图最大点权独立集) 解题报告
- Educational Codeforces Round 1 F Cut Length(计算几何)
- Educational Codeforces Round 20 F. Coprime Subsequences(容斥)
- Educational Codeforces Round 19 F(dp+队列优化)
- Educational Codeforces Round 8 F. Bear and Fair Set(最大流 | Hall定理)
- Educational Codeforces Round 8 F. Bear and Fair Set(最大流 | Hall定理)★
- CodeForces 825F Educational Round #25 F:KMP最小循环节+DP
- Educational Codeforces Round 5 [补F]
- Educational Codeforces Round 23 A-F
- Educational Codeforces Round 32 F. Connecting Vertices
- Educational Codeforces Round 31 F. Anti-Palindromize
- [Educational Codeforces Round 17 F (762F)] Tree nesting
- [最小生成树] Codeforces 632F Educational Codeforces Round 9 F. Magic Matrix & SRM 687 div1 AllGraphCuts
- Educational Codeforces Round 23 F. MEX Queries(离散化+线段树)
- Educational Codeforces Round 28 F. Random Query 期望(贡献思想)
- Educational Codeforces Round 23 F. MEX Queries(线段树区间设值)
- Educational Codeforces Round 32【solved: 6 / 7】(F待补)
- spring_SSH整合之_OpenSessionInView
- Android 线程模型和Looper深入理解
- javascript中的this---you don't know js学习笔记(一)
- Android统计图表MPAndroidChart
- [LeetCode] Target Sum通过添加+/-获得目标结果
- Codeforces Educational Round#21 F(808F) Solution:网络流(最小割)
- 生活随笔:人脉网、管理人、看人、投资
- 什么是算法,为什么需要学算法,以及算法学到什么程度
- leetcode 40. Combination Sum II
- 一个IT人士的个人经历,给迷失方向的朋友
- Python中列表的copy方法
- Linux之线程的创建、等待、终止及分离
- ES 其他公司使用参考
- 三、数据库连接池