标签:second names flag reg tarjan air continue clu back
题目分析:
如果一个双连通分量是简单环,那么用polya原理计数循环移位即可。
如果一个双连通分量不是简单环,那么它必然可以两两互换,不信你可以证明一下相邻的可以互换。
如果一条边是桥,那么直接乘以k就行了。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 4 const int mod = 1000000007; 5 const int maxn = 110; 6 7 int n,m,k; 8 vector <int> g[maxn]; 9 10 int fa[maxn],arr[maxn],dfn[maxn],bccnum,low[maxn],cl; 11 12 vector <pair<int,int> > bcc[maxn]; 13 vector <int> hhh[maxn]; 14 15 void read(){ 16 scanf("%d%d%d",&n,&m,&k); 17 for(register int i=1;i<=m;i++){ 18 int u,v; scanf("%d%d",&u,&v); 19 g[u].push_back(v); g[v].push_back(u); 20 } 21 } 22 23 stack<int> sta; 24 void Tarjan(int now,int f){ 25 fa[now] = f; 26 low[now] = dfn[now] = ++cl; 27 sta.push(now); 28 for(int i=0;i<g[now].size();i++){ 29 if(g[now][i] == f) continue; 30 if(dfn[g[now][i]] > dfn[now]) continue; 31 if(!dfn[g[now][i]]){ 32 Tarjan(g[now][i],now); 33 low[now] = min(low[now],low[g[now][i]]); 34 }else{ 35 low[now] = min(low[now],dfn[g[now][i]]); 36 hhh[now].push_back(g[now][i]); 37 } 38 } 39 if(f == 0 || low[now] >= dfn[fa[now]]){ 40 bccnum++; 41 while(true){ 42 int k = sta.top();sta.pop(); 43 arr[k] = 1; 44 if(fa[k] == 0) break; 45 bcc[bccnum].push_back(make_pair(k,fa[k])); 46 for(int i=0;i<hhh[k].size();i++){ 47 bcc[bccnum].push_back(make_pair(k,hhh[k][i])); 48 } 49 if(k == now) break; 50 } 51 if(bcc[bccnum].size() == 0) bccnum--; 52 } 53 } 54 55 int C[maxn*2][maxn*2]; 56 57 int fast_pow(int now,int pw){ 58 int ans = 1,dt = now, bit = 1; 59 while(bit <= pw){ 60 if(bit & pw){ans =1ll*ans*dt%mod;} 61 dt = 1ll*dt*dt%mod; bit<<=1; 62 } 63 return ans; 64 } 65 66 int solve(int now){ 67 int ans = 0; 68 for(register int i=1;i<=now;i++){ 69 ans += fast_pow(k,__gcd(now,i)); 70 ans %= mod; 71 } 72 ans = 1ll*ans*fast_pow(now,mod-2)%mod; 73 return ans; 74 } 75 76 int hap[maxn]; 77 void work(){ 78 for(register int i=1;i<=n;i++){ 79 if(arr[i]) continue; 80 Tarjan(i,0); 81 } 82 C[0][0] = 1; 83 for(register int i=1;i<=200;i++){ 84 C[i][0] = C[i][i] = 1; 85 for(register int j=1;j<i;j++){ 86 C[i][j] = (C[i-1][j] + C[i-1][j-1])%mod; 87 } 88 } 89 int ans = 1; 90 for(register int i=1;i<=bccnum;i++){ 91 int flag = 2; 92 for(register int j=0;j<bcc[i].size();j++){ 93 if(hap[bcc[i][j].first] && hap[bcc[i][j].second]) flag--; 94 hap[bcc[i][j].first]++; hap[bcc[i][j].second]++; 95 } 96 for(register int j=0;j<bcc[i].size();j++){ 97 hap[bcc[i][j].first]--; hap[bcc[i][j].second]--; 98 } 99 if(flag == 1 || flag == 2){ 100 if(bcc[i].size() == 1) ans = 1ll*ans*k%mod; 101 else ans = 1ll*ans*solve(bcc[i].size())%mod; 102 }else{ 103 ans = 1ll*ans*C[bcc[i].size()+k-1][k-1]%mod; 104 } 105 } 106 printf("%d",ans); 107 } 108 109 int main(){ 110 read(); 111 work(); 112 return 0; 113 }
AtcoderARC062F Painting Graphs with AtCoDeer 【双连通分量】【polya原理】
标签:second names flag reg tarjan air continue clu back
原文地址:https://www.cnblogs.com/Menhera/p/9845753.html