标签:int main 情况 img pen close i++ size 公倍数
【题意】
给定一个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; }
标签:int main 情况 img pen close i++ size 公倍数
原文地址:https://www.cnblogs.com/betablewaloot/p/12207877.html