CF808F Card Game 网络流
首先答案肯定有单调性,先二分出答案
然后如何保证c[i]+c[j]不为质数
如果同奇偶的话,除了1和1,其他必不为质数,否则可以for循环暴力判一下
所以如果是质数,必定为一奇一偶,这两点不能同时选
启发了我们可以把点分开来,奇数在一边,偶数在一边,在不能同时选的两点间连inf的边(因为inf不能被割掉,所以肯定是两边的点有一个被割掉)
然后就变成了很经典的,"假设全部获利,割掉表示不要,求最小化损失也就是最大化获利"的模型了
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int inf=INT_MAX; const int maxn=10000; struct lys{ ll from,to,nxt,c; }e[maxn*4]; ll cnt=1,n,m,k,s,t,dep[maxn],head[maxn],val[maxn],cur[maxn]; void add(int from,int to,ll c) { cnt++; e[cnt].from=from;e[cnt].to=to;e[cnt].nxt=head[from];head[from]=cnt;val[cnt]=c; } bool bfs() { queue<int>q; memset(dep,0,sizeof(dep)); q.push(s); dep[s]=1; cur[s]=head[s]; while(!q.empty()) { int u=q.front(); q.pop(); for(int i=head[u];i;i=e[i].nxt) { int to=e[i].to; if(val[i]&&!dep[to]) { dep[to]=dep[u]+1; cur[to]=head[to]; q.push(to); } } } return dep[t]; } ll dfs(int u,ll in) { if(u==t) return in; ll out=0; for(int i=cur[u];i&∈i=e[i].nxt) { cur[u]=i; int to=e[i].to; if(val[i]&&dep[to]==dep[u]+1) { ll res=dfs(to,min(val[i],in)); val[i]-=res; val[i^1]+=res; in-=res; out+=res; } } if(!out) dep[u]=0; return out; } int prime[int(2e5)+5], pri_cnt=0 ; bool vis[int(2e5)+5]; //0表示是素数,1表示是合数 void get_prime(int n) { for (int i = 2; i <= n; i++) { //这里直接跳过1 if (!vis[i]) prime[pri_cnt++] = i; //记录素数 for (int j = 0; j < pri_cnt && i * prime[j] <= n; j++) { vis[i * prime[j]] = true; if (i % prime[j] == 0) //避免重复筛选 break; } } } int p[maxn],c[maxn],l[maxn],use[maxn]; bool valid(int level){ memset(use,0,sizeof(use)); for(int i=1;i<=n;i++) if(l[i]<=level) use[i]=1; // deal with "1" int mx=-1; for(int i=1;i<=n;i++) if(c[i]==1&&use[i]) mx=max(mx,p[i]); if(mx!=-1){ for(int i=1;i<=n;i++) if(c[i]==1&&use[i]) use[i]=0; bool find=false; for(int i=1;i<=n&&!find;i++) { if(c[i]==1&&p[i]==mx&&l[i]<=level) use[i]=1,find=true; } } cnt=1; memset(head,0,sizeof(head)); memset(val,0,sizeof(val)); memset(cur,0,sizeof(cur)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++){ if(i==j) continue; if(!use[i]||!use[j]) continue; if(!vis[c[i]+c[j]]) { // 左odd 右even if(c[i]%2){ add(i,j,inf); add(j,i,0); } else { add(j,i,inf); add(i,j,0); } } } s=0,t=n+1; ll sum=0; for(int i=1;i<=n;i++){ if(!use[i]) continue; sum+=p[i]; if(c[i]%2){ add(s,i,p[i]); add(i,s,0); } else { add(i,t,p[i]); add(t,i,0); } } ll ans=0; while(bfs()) ans+=dfs(s,1e18); if(sum-ans>=k) return true; else return false; } int main() { //freopen("lys.in","r",stdin); get_prime(2e5); cin>>n>>k; int odd=0,even=0; for(int i=1;i<=n;i++) cin>>p[i]>>c[i]>>l[i]; int l=1,r=n,out=-1; while(l<=r){ int mid=l+r>>1; if(valid(mid)){ out=mid; r=mid-1; } else l=mid+1; } cout<<out; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)