【ARC062F】Painting Graphs with AtCoDeer【双联通分量】【Polya定理】

题解
相关
感觉都讲得挺清楚的了。
代码挺矬的。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
using namespace std;
const int N=55,M=205,mod=1000000007;
int n,m,k,u,v,cnt,tot,idx,ans,head[N],id[M],to[M],nxt[M],dfn[N],low[N],in[N],stk[M];
bool ck[M];
set<int> st;
void adde(int u,int v){
    to[++cnt]=v;
    nxt[cnt]=head[u];
    head[u]=cnt;
}
int fastpow(int a,int x){
    int res=1;
    while(x){
        if(x&1){
            res=1LL*res*a%mod;
        }
        x>>=1;
        a=1LL*a*a%mod;
    }
    return res;
}
int gcd(int a,int b){
    return b?gcd(b,a%b):a;
}
int C(int n,int m){
    int res=1;
    for(int i=1;i<=m;i++){
        res=1LL*res*(n-i+1)%mod*fastpow(i,mod-2)%mod;
    }
    return res;
}
void tarjan(int pre,int u){
    dfn[u]=low[u]=++idx;
    for(int v=head[u];v;v=nxt[v]){
        if(to[v]!=pre&&!ck[id[v]]){
            ck[id[v]]=true;
            stk[++stk[0]]=v;
        }
        if(!dfn[to[v]]){
            tarjan(u,to[v]);
            low[u]=min(low[u],low[to[v]]);
            if(low[to[v]]>=dfn[u]){
                tot++;
                int siz=0;
                st.clear();
                memset(in,0,sizeof(in));
                do{
                    st.insert(to[stk[stk[0]]]);
                    st.insert(to[stk[stk[0]]^1]);
                    in[to[stk[stk[0]]]]++;
                    in[to[stk[stk[0]]^1]]++;
                    siz++;
                }while(id[v]!=id[stk[stk[0]--]]);
                bool flag=true;
                for(set<int>::iterator it=st.begin();it!=st.end();it++){
                    if(in[*it]!=2){
                        flag=false;
                        break;
                    }
                }
                if(flag==true||siz==1){
                    int tmp=0;
                    for(int i=0;i<siz;i++){
                        tmp=(tmp+fastpow(k,gcd(i,siz)))%mod;
                    }
                    ans=(1LL*ans*tmp%mod*fastpow(siz,mod-2)%mod)%mod;
                }else{
                    ans=1LL*ans*C(siz+k-1,k-1)%mod;
                }
            }
        }else{
            low[u]=min(low[u],dfn[to[v]]);
        }
    }
}
int main(){
    scanf("%d%d%d",&n,&m,&k);
    ans=cnt=1;
    for(int i=1;i<=m;i++){
        scanf("%d%d",&u,&v);
        adde(u,v);
        id[cnt]=i;
        adde(v,u);
        id[cnt]=i;
    }
    for(int i=1;i<=n;i++){
        if(!dfn[i]){
            tarjan(0,i);
        }
    }
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/ez_2016gdgzoi471/article/details/81637681
今日推荐