CodeForces - 76A:Gift (最小生成树 解决单调性问题是思想)
Posted hua-dong
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CodeForces - 76A:Gift (最小生成树 解决单调性问题是思想)相关的知识,希望对你有一定的参考价值。
题意:给定N点M边的无向连通图,每条边有两个权值(g,s)。 给定G,S。 让你给出一组(g0,s0)使得图中仅留下g<=g0, s<=s0的边之后,依然连通,并求Gg0+Ss0的最小值。 n<=200,m<=50000。
思路:枚举g0,求最小的s0,满足生成MST。 把边按g排序,一条边一条边的加入,然后在加入边的集合里面找出最小的s。但是每次排序复杂度过高,而且边数也过多,(LCT做也行吧,就不需要考虑这么多)。 我们去优化暴力的做法。假设新加入一条边,显然最多改变一条边,那么我们维护一个有序序列,表示MST用的边(N-1条),新加入后,手动排序(O(N)),然后把这N条边建立新的MST,就可以了。
#include<bits/stdc++.h> #define ll long long #define pair<ll,ll> pii #define x first #define y second #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=200010; struct in int u,v;ll a,b; s[maxn]; bool cmp(in p,in q) if(p.a!=q.a) return p.a<q.a; return p.b<q.b; int fa[maxn],q[maxn]; int find(int x) if(x==fa[x]) return x; return fa[x]=find(fa[x]); int main() int N,M,tot=0; ll G,S,A=0,B=0,ans=-1; scanf("%d%d%lld%lld",&N,&M,&G,&S); rep(i,1,M) scanf("%d%d%lld%lld",&s[i].u,&s[i].v,&s[i].a,&s[i].b); if(s[i].u==s[i].v) i--,M--; sort(s+1,s+M+1,cmp); rep(i,1,M) q[++tot]=i; int t=tot; while(t>1&&s[q[t]].b<s[q[t-1]].b) swap(q[t],q[t-1]),t--; rep(j,1,N) fa[j]=j; tot=0; rep(j,1,N) int fu=find(s[q[j]].u); int fv=find(s[q[j]].v); if(fu==fv) continue; fa[fu]=fv; q[++tot]=q[j]; if(tot==N-1) break; if(tot==N-1) if(ans==-1) ans=G*s[i].a+S*s[q[N-1]].b; else ans=min(ans,G*s[i].a+S*s[q[N-1]].b); printf("%lld\n",ans); return 0;
以上是关于CodeForces - 76A:Gift (最小生成树 解决单调性问题是思想)的主要内容,如果未能解决你的问题,请参考以下文章
Prime Gift CodeForces - 912E (中途相遇)
Codeforces 506E Mr. Kitayuta's Gift - 动态规划 - 矩阵
CodeForces - 1538G Gift Set(二分)
Codeforces 912 E.Prime Gift (折半枚举二分)
Codeforces 506EMr.Kitayuta’s Gift&&BZOJ 4214黄昏下的礼物 dp转有限状态自动机+矩阵乘法优化