ssoj1018地下组织

来源:互联网 发布:淘宝美即官网是正品吗 编辑:程序博客网 时间:2024/04/28 08:50

【题意】他要让一些人有联络方式, 使得每个人都可以直接戒者间接的联系其他人。当然, 为了让地下组织保持隐蔽, 建立的联络方式越少越好。 Nc现在有m对可以选择建立的联络方式。 对于每对选择, 都有一个特定的花费。 建立好一个完善的联络方式的总花费, 是选择的每对关系的花费的最大公约数。 当然,建立好一个完善联络方式的方法也还是不唯一。 现在nc想知道, 对于所有的可能的方法, 都会有一个总花费。 他想知道这些总花费的最小公倍数。

【思路】记录图中边权的所有质因数,枚举这些质因数x最为最大公约数的因数,将x的次数转化成克鲁斯卡尔的费用,用克鲁斯卡尔跑一边,x次数最小的就是这条路的最大公因数,乘入ans。

【代码】

#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#define ll long longusing namespace std;const int maxn=1003;const int maxm=100005;const ll mod=(ll)1<<31;struct data{    int u,v,w;    bool operator<(const data&b)const{        return w>b.w;    }}e[maxm*2],g[maxm*2];int n,m,pt=0,p[maxm],num,fa[maxm],vst[maxm];ll ans=1;inline int get(){    char c;while(!isdigit(c=getchar()));    int v=c-48;while(isdigit(c=getchar()))v=v*10+c-48;    return v;}inline void getprime(){    memset(vst,0,sizeof(vst));    for(int t=1;t<=m;++t){        int c=g[t].w;        for(int i=2;i*i<=g[t].w;++i)if(c%i==0){            while(c%i==0)c/=i;            if(!vst[i])p[++pt]=i;            ++vst[i];        }        if(c>1&&!vst[c])p[++pt]=c;++vst[c];    }}inline void gettot(int x,int pri){//将质因数的次数作为krus的边权    int t=0;int c=g[x].w;e[++num]=g[x];    while(c%pri==0)c/=pri,++t;    e[num].w=t;}inline int Find(int x){    if(fa[x]==x)return fa[x];    else return (fa[x]=Find(fa[x]));}inline int krus(){    int cnt=0,tme=0;    sort(e+1,e+1+num);    for(int i=1;i<=n;++i)fa[i]=i;    for(int i=1;i<=num;++i){        int x=Find(fa[e[i].u]);        int y=Find(fa[e[i].v]);        if(x!=y)++cnt,fa[y]=x,tme=e[i].w;    }    if(cnt==n-1)return tme;    else return 0;}inline ll Pow(int a,int b){    ll tmp=a,ret=1;    while(b){        if(b&1)ret=ret*tmp%mod;        tmp=tmp*tmp%mod;        b>>=1;    }    return ret;}int main(){    n=get();m=get();    for(int i=1;i<=m;++i)g[i].u=get(),g[i].v=get(),g[i].w=get();    getprime();    int tmp=0;    for(int i=1;i<=pt;++i)if(vst[p[i]]>=n-1){//枚举质因数        num=0;        for(int j=1;j<=m;++j)if(g[j].w%p[i]==0)gettot(j,p[i]);        if(num>=n-1){            int t=krus();            if(t)ans=ans*Pow(p[i],t)%mod;        }    }    printf("%lld\n",ans);    return 0;}


0 0
原创粉丝点击