Pjudge #21614. 守卫/2021-2022 ICPC North America Championships. Problem I
2022/4/3 23:23:57
本文主要是介绍Pjudge #21614. 守卫/2021-2022 ICPC North America Championships. Problem I,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
题面传送门
首先显然是在最小生成树上搞的。
可以发现,如果有\(k_1,k_2\dots k_m\)这些村庄被派遣了守卫,那么被断掉的边一定是两两点对间的最大边,容易证明这只有\(k-1\)条。
不难想到建立Kruskal重构树,然后一个额外点要选的话那么两个儿子中都有守卫。
我们将守卫看作流,那么对于每个节点,先保证往上,再走选择这条边。
因为Kruskal重构树具有单调性,可以发现本来它自己就会往上流,只要在最高的节点连到T点一条inf的边就好了。
然后跑个最大费用最大流就好了,-1的边界仔细判判。
code:
#include<bits/stdc++.h> #define I inline #define max(a,b) ((a)>(b)?(a):(b)) #define min(a,b) ((a)<(b)?(a):(b)) #define abs(x) ((x)>0?(x):-(x)) #define ll long long #define db double #define lb long db #define N (300+5) #define M (900+5) #define K (200000+5) #define mod 9248440332 #define Mod (mod-1) #define eps (1e-9) #define U unsigned int #define it iterator #define Gc() getchar() #define Me(x,y) memset(x,y,sizeof(x)) #define Mc(x,y) memcpy(x,y,sizeof(x)) #define d(x,y) (n*(x-1)+(y)) #define R(n) (rand()*rand()%(n)+1) #define Pc(x) putchar(x) #define LB lower_bound #define UB upper_bound #define PB push_back using namespace std; int Fl[N],n,m,k,x,y,z,fa[M],W[M],S,T,cnt,Ans; struct Ques{int x,y,z;}Q[N*N];I bool cmp(Ques x,Ques y){return x.z<y.z;} I int GF(int x){return fa[x]^x?fa[x]=GF(fa[x]):x;} struct yyy{int to,g,w,z;};struct ljb{int head=1,h[M+5];yyy f[M*M+5];I void add(int x,int y,int g,int w){f[++head]=(yyy){y,g,w,h[x]};h[x]=head;}}s; I void Ins(int x,int y,int g,int w){s.add(x,y,g,w);s.add(y,x,0,-w);} namespace EK{ int pre[M],g[M],d[M],Ans,ToT;queue<int> Q;yyy tmp;I int bfs(){ Q.push(S);Me(d,-0x3f);g[S]=1e9;d[S]=0;while(!Q.empty()){ x=Q.front();Q.pop();for(int i=s.h[x];i;i=tmp.z){ tmp=s.f[i];if(d[tmp.to]>=d[x]+tmp.w||!tmp.g) continue;;g[tmp.to]=min(g[x],tmp.g);d[tmp.to]=d[x]+tmp.w;pre[tmp.to]=i;Q.push(tmp.to); } }return d[T]>=0; }I int calc(){while(bfs()) {Ans+=g[T]*d[T];ToT+=g[T];for(x=T;x^S;x=s.f[pre[x]^1].to) s.f[pre[x]].g-=g[T],s.f[pre[x]^1].g+=g[T];}if(ToT^k){puts("-1");exit(0);}return Ans;} } int main(){ freopen("1.in","r",stdin); int i;scanf("%d%d%d",&n,&m,&k);for(i=1;i<=m;i++) scanf("%d%d%d",&Q[i].x,&Q[i].y,&Q[i].z);sort(Q+1,Q+m+1,cmp); cnt=n;for(i=1;i<=2*n;i++) fa[i]=i;for(i=1;i<=m;i++) GF(Q[i].x)^GF(Q[i].y)&&(W[++cnt]=Q[i].z,Ans+=Q[i].z,Ins(GF(Q[i].x),cnt,1,0),Ins(GF(Q[i].y),cnt,1,0),fa[GF(Q[i].x)]=fa[GF(Q[i].y)]=cnt); S=0;T=k+cnt+1;for(i=1;i<=k;i++) {Ins(S,cnt+i,1,0);scanf("%d",&x);while(x--) scanf("%d",&y),Fl[y]=1,Ins(cnt+i,y,1,0);}for(i=n+1;i<=cnt;i++) Ins(i,T,1,W[i]);for(i=1;i<=cnt;i++)GF(i)==i&&(Ins(i,T,1,1e7),0); for(i=1;i<=n;i++) Fl[GF(i)]|=Fl[i];for(i=1;i<=cnt;i++) if(GF(i)==i&&!Fl[i]&&n^1){puts("-1");return 0;} printf("%d\n",Ans-EK::calc()%(10000000)); }
这篇关于Pjudge #21614. 守卫/2021-2022 ICPC North America Championships. Problem I的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-26RocketMQ入门指南:搭建与使用全流程详解
- 2024-11-26RocketMQ入门教程:轻松搭建与使用指南
- 2024-11-26手写RocketMQ:从入门到实践的简单教程
- 2024-11-25【机器学习(二)】分类和回归任务-决策树(Decision Tree,DT)算法-Sentosa_DSML社区版
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享