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
原文地址:https://www.cnblogs.com/betablewaloot/p/12207877.html