zoukankan      html  css  js  c++  java
  • [机房测试]万花筒

    Descrption

    初始 \(m\) 条边,如果 \((u,v)\) 在图中,那么将 \(((u+1)\bmod n+1,(v+1)\bmod n+1)\) 也加入图中。求该图的最小生成树,\(1\leq n\leq 10^9,1\leq m \leq 10^5\)

    Solution

    先考虑暴力求最小生成树,那么一共会有 \(nm\) 条边。但是会发现这些边是有一定规律的。我们将通过 \((u,v)\) 生成的边化为一类。发现如果将这类边全部连起来,会将图化为 \(\gcd(n,abs(u-v))\) 个连通块,连通块内部就不管了,直接减作 \(\gcd(n,abs(u-v))\) 个点。所以可以同时处理一类边的情况。这样就可以做到 \(O(m\log m)\)

    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    using namespace std;
    
    typedef long long ll;
    
    inline int read(){
        int x=0,flag=1; char c=getchar();
        while(c<'0'||c>'9'){if(c=='-')flag=0;c=getchar();}
        while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+c-48;c=getchar();}
        return flag? x:-x;
    }
    
    struct E{
        int type,w;
        E(int type_=0,int w_=0):type(type_),w(w_){}
        bool operator <(const E &X) const{
            return w<X.w;
        }
    };
    
    vector<E> e;
    int gcd(int x,int y){
        return y? gcd(y,x%y):x;
    }
    
    int main(){
        freopen("kaleidoscope.in","r",stdin);
        freopen("kaleidoscope.out","w",stdout);
        int T=read();
        while(T--){
            ll ans=0; e.clear();
            int n=read(),m=read();
            for(int i=1;i<=m;i++){
                int u=read(),v=read(),w=read();
                e.push_back(E(abs(u-v),w));
            }
            sort(e.begin(),e.end());
            int now=n;
            for(E t:e){
                int x=gcd(t.type,now);
                if(x==now) continue;
                ans+=1ll*(now-x)*t.w;
                now=x; if(x==1) break;
            }
            printf("%lld\n",ans);
        }
    }
    
  • 相关阅读:
    背水一战 Windows 10 (90)
    背水一战 Windows 10 (89)
    背水一战 Windows 10 (88)
    背水一战 Windows 10 (87)
    背水一战 Windows 10 (86)
    背水一战 Windows 10 (85)
    背水一战 Windows 10 (84)
    背水一战 Windows 10 (83)
    背水一战 Windows 10 (82)
    背水一战 Windows 10 (81)
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/15422485.html
Copyright © 2011-2022 走看看