码迷,mamicode.com
首页 > 其他好文 > 详细

AtcoderARC062F Painting Graphs with AtCoDeer 【双连通分量】【polya原理】

时间:2018-10-24 22:18:43      阅读:242      评论:0      收藏:0      [点我收藏+]

标签: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

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!