zoukankan      html  css  js  c++  java
  • 1713:生成树

    【题意】

     

    给定一个n个点m条边的无向图,求图中所有生成树边权最大公约数的最小公倍数。

     

    【数据规模】

    对于20%的数据,M=N-1;

    对于另外20%的数据,M=N;

    对于另外30%的数据,所有边权都是2的整数次幂;

    对于100%的数据,N≤1000,M≤100000,di≤215-1,ans≤264-1。

    【题解】

    先考虑边权都是2的整数次幂的情况,我们可以将每条边的权值改为次数跑最大生成树,2的树上权值最小的边次幂就是答案。

     

    那么我们可以考虑相同做法,对每个边权分解质因数,将该边关于该质因数的次数加入该质因数的vector中,对于每个质因数跑最大生成树,最终答案相乘即可。

    代码如下:

    #include<bits/stdc++.h>
    #define int long long
    using namespace std;
    const int N=1005,M=100005;
    int n,m,ans,zhi[70005],top,ne[70000],fa[N];
    struct pigu
    {
        int co,dao,quan;
    }a[M];
    vector <pigu> ve[70000];
    bool book[70000];
    inline int read()
    {
        char c=getchar();
        int x=0,f=1;
        while(!isdigit(c)) {if(c=='-') f=-1;c=getchar();}
        while(isdigit(c)) {x=(x<<3)+(x<<1)+c-'0';c=getchar();}
        return x*f;
    }
    inline int find(int x)
    {
        if(fa[x]==x) return x;
        fa[x]=find(fa[x]);
        return fa[x];
    }
    inline void ycl()
    {
        for(int i=2;i<=67000;i++)
        {
            if(book[i]==0)
                zhi[++top]=i,ne[i]=i;
            for(int j=1;j<=top&&zhi[j]*i<=67000;j++)
            {
                book[zhi[j]*i]=1;
                ne[zhi[j]*i]=zhi[j];
                if(i%zhi[j]==0) break;
            }
        }
    }
    inline bool cmp(pigu x,pigu y)
    {
        return x.quan>y.quan;
    }
    inline int zxscs(int x)
    {
        int huan=ve[x].size();
        sort(ve[x].begin(),ve[x].end(),cmp);
        for(int i=1;i<=n;i++) fa[i]=i;
        int cnt=0;
        for(int i=0;i<huan;i++)
        {
            int fa1=find(ve[x][i].co),fa2=find(ve[x][i].dao);
            if(fa1!=fa2)
            {
                cnt++;
                fa[fa1]=fa2;
            }
            if(cnt==n-1) return ve[x][i].quan;
        }
        return 0;
    }
    signed main()
    {
        n=read();m=read();
        ycl();
        for(int i=1;i<=m;i++)
        {
            a[i].co=read();a[i].dao=read();a[i].quan=read();
            pigu dahu=a[i];
            int hu=a[i].quan;
            while(hu>1)
            {    
                int gu=0,ha=ne[hu];
                while(ne[hu]==ha)
                {
                    gu++;
                    hu/=ne[hu];
                }
                dahu.quan=gu;
                ve[ha].push_back(dahu);
            }
            dahu.quan=1;
            ve[1].push_back(dahu);
        }
        if(zxscs(1)==0)
        {
            cout<<"0";
            return 0;
        }ans=1;
        for(int i=2;i<=67000;i++)
        {
            int hu=ve[i].size();
            if(hu>=n-1) 
            {
                int ga=1,ha=zxscs(i);
                while(ha--) ga*=i;
                ans*=ga;
            }
        }
        cout<<ans;
    }
    View Code
  • 相关阅读:
    linux ubuntu装机到可实现java(eclipse,intellij IDEA,android)开发全过程
    浅谈线程同步的几种方法
    KMP算法,这是我看到的最简单的最好理解的KMP算法
    常用基础算法C++实现
    堆内存和栈内存详解(转载)
    数据结构=。= 链表
    倒排索引--资料1
    倒排索引简单理解
    简单理解Socket
    8.结构体的使用 2015.12.3
  • 原文地址:https://www.cnblogs.com/betablewaloot/p/12207877.html
Copyright © 2011-2022 走看看