ARC 062 F AT2143 AtCoDeerくんとグラフ色塗り / Painting Graphs with AtCoDeer(burnside引理+点双)

题目

分单边,
单环,
复环来讨论。
发现复环中可以交换任意两条边的颜色,直接组合数即可。
单环用burnside引理。
单边直接乘。

A C   C o d e \rm AC \ Code AC Code

#define maxn 55
#define maxm 205
#define mod 1000000007
using namespace std;

int n,m,k;
int info[maxn],Prev[maxm],to[maxm],cnt_e;
void Node(int u,int v){ Prev[++cnt_e]=info[u],info[u]=cnt_e,to[cnt_e]=v; }

int dfn[maxn],low[maxn],sta[maxn],tot,fac[maxm]={1,1},inv[maxm]={1,1},invf[maxm]={1,1};
int vis[maxn],tim;
vector<vector<int> >pd;
void dfs(int u){
	dfn[u] = low[u] = ++tot;sta[++sta[0]] = u;
	for(int i=info[u],v;i;i=Prev[i]) if(!dfn[v=to[i]]){
		dfs(v);
		if(low[v] >= dfn[u]){
			vector<int>p;p.push_back(u);
			for(int t = -1;t!=v;)
				p.push_back(t = sta[sta[0]--]);
			pd.push_back(p);
		}
		low[u] = min(low[u] , low[v]);
	}else low[u] = min(low[u] , dfn[v]);
}

int Pow(int base,int k){
	int ret = 1;
	for(;k;k>>=1,base=1ll*base*base%mod) if(k&1) ret=1ll*ret*base%mod;
	return ret;
}

int C(int a,int b){ return 1ll * fac[a] * invf[b] % mod * invf[a-b] % mod; }

int main(){
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1,u,v;i<=m;i++) scanf("%d%d",&u,&v),Node(u,v),Node(v,u);
	for(int i=2;i<maxm;i++) 
		fac[i] = 1ll * fac[i-1] * i % mod,
		inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod ,
		invf[i] = 1ll * invf[i-1] * inv[i] % mod;
	for(int i=1;i<=n;i++) if(!dfn[i]) dfs(i);
	int ans = 1;
	for(auto U:pd){
		++tim;
		for(int u:U) vis[u] = tim;
		int cnt = 2*U.size();
		for(int u:U) for(int i=info[u],v;i;i=Prev[i]) 
			if(vis[v=to[i]]==tim) cnt--;
		if(cnt>0) ans = 1ll * ans * k % mod;
		else if(cnt == 0){
			int sum = 0;
			for(int i=1;i<=U.size();i++)
				sum = (sum + Pow(k,__gcd((int)U.size(),i))) % mod;
			ans = 1ll * ans * sum % mod * Pow(U.size(),mod-2) % mod;
		}else ans = 1ll * ans * C(U.size()-cnt/2+k-1,k-1) % mod;
	}
	printf("%d\n",(ans+mod)%mod);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值