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 (最小生成树 解决单调性问题是思想)的主要内容,如果未能解决你的问题,请参考以下文章

(最小生成树)Codeforces 76 A 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转有限状态自动机+矩阵乘法优化