Description
Solution 1
這個圖只有5條返祖邊所以才能做,
先把所有有返祖邊的點拿出來,(姑且叫做返祖點)
自然地,考慮容斥,枚舉一條返祖邊的兩個點是否同色,以及返祖邊點之間的染色情況,
枚舉後DP計算,設表示點x染顏色i時的方案數,注意顏色0表示其他顏色,即沒有被枚舉的顏色,
因爲有6條返祖邊,所以染色情況最多877種(貝爾數),每次DP至少需要O(n)時間,過不了考慮優化,
顯然的,所有度數爲1的點都可以刪掉,他們對ans的貢獻恆爲(K-1),
刪完以後再把鏈縮一下就是返祖點構成的虛樹了,
縮鏈簡單,像矩陣乘法那樣弄就好了,
這樣每次DP的複雜度就很小了,直接在虛樹上跑即可,
複雜度:
(前面的預處理+後面的枚舉及DP)
Solution 2
先轉化一下,
原圖的每條邊都有兩個值(a,b),分別表示如果兩個點同色的貢獻和不同色的貢獻,
對於一種染色方案,答案爲所有邊的貢獻乘起來,
顯然的,對於原圖,每條邊的值爲(0,1),
考慮縮點,
顯然的葉子可以直接縮點,他們對ans的貢獻恆爲(K-1),
對於度數爲2的點,可以通過以下方式縮掉:
設點數爲2,它連向的兩個點爲,邊的值爲,邊的值爲,
刪去點以及其連出去的邊,
添加邊,其值爲
這樣不停的縮點,最後最多隻會剩下10個點15條邊,
這麼小暴力即可,跑個狀壓DP子集轉移之類的即可
Code
#include <cstdio>
#include <algorithm>
#include <iostream>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define efo(i,q) for(int i=A[q];i;i=B[i][0])
#define min(q,w) ((q)>(w)?(w):(q))
#define max(q,w) ((q)<(w)?(w):(q))
using namespace std;
typedef long long LL;
const int N=100500,mo=1e9+7;
int read(int &n)
{
char ch=' ';int q=0,w=1;
for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());
if(ch=='-')w=-1,ch=getchar();
for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;
}
int m,n,K,root;
LL ans;
int B[2*N][3],A[N],B0=1,Bv[N];
int Fa[N],Fav[N],Jp[N],d[N];
int HU[10][2],HU0;
int z[N];
int g[7][N][7][7],gmx;
LL f[N][9];
LL jc[N],jcn[N];
int MOJ(LL &q,int w){return (q+=w)>=mo?q-=mo:q;}
int MOJ(int &q,int w){return (q+=w)>=mo?q-=mo:q;}
LL ksm(LL q,int w)
{
LL ans=1;
for(;w;w>>=1,q=q*q%mo)if(w&1)ans=ans*q%mo;
return ans;
}
LL P(int m,int n){return jc[m]*jcn[m-n]%mo;}
void link(int q,int w)
{
++Bv[q],++Bv[w];
B[++B0][0]=A[q],A[q]=B0,B[B0][1]=w;
B[++B0][0]=A[w],A[w]=B0,B[B0][1]=q;
}
void dfsh(int q,int fa)
{
z[q]=1;
efo(i,q)if(!B[i][2]&&B[i][1]!=fa)
{
if(!z[B[i][1]])dfsh(B[i][1],q);
else B[i][2]=B[i^1][2]=1,HU[++HU0][0]=q,HU[HU0][1]=B[i][1];
}
}
int dfsf(int q,int fa,int c)
{
Fav[q]=max(0,c-1);gmx=max(gmx,Fav[q]);
Jp[q]=q;Fa[q]=fa;
f[q][0]=1;
if(B[B[A[q]][0]][0])c=0;
efo(i,q)if(!B[i][2]&&B[i][1]!=fa)
{
Jp[q]=dfsf(B[i][1],q,c+1);
f[q][0]=f[q][0]*f[B[i][1]][0]%mo*(K-1LL)%mo;
}
return (B[B[A[q]][0]][0]||!fa)?(Jp[q]=q):Jp[q];
}
void dfs(int q,int fa,int cnt)
{
int Q=q;q=Jp[q];
fo(i,0,cnt)f[q][i]=1;
efo(i,q)if(!B[i][2]&&B[i][1]!=Fa[q])
{
dfs(B[i][1],q,cnt);
LL t=f[B[i][1]][0]*(K-cnt-1)%mo;
fo(j,1,cnt)MOJ(t,f[B[i][1]][j]);
f[q][0]=f[q][0]*(t)%mo;
MOJ(t,f[B[i][1]][0]);
fo(j,1,cnt)f[q][j]=f[q][j]*(t-f[B[i][1]][j])%mo;
}
if(z[q])
{
if(z[q]<=cnt)
{
fo(i,0,cnt)if(i!=z[q])f[q][i]=0;
}
else fo(i,1,cnt)f[q][i]=0;
}
if(Fav[q])
{
fo(i,0,cnt)
fo(j,0,cnt)f[0][i]=(f[0][i]+f[q][j]*g[cnt][Fav[q]][i][j])%mo;
fo(i,0,cnt)f[Q][i]=f[0][i],f[0][i]=0;
}
}
void ss(int q,int w,int e)
{
if(q>HU0)
{
if(!w)return;
w=min(w,K-1);
dfs(root,0,w);
f[root][0]=f[root][0]*(K-w)%mo;
fo(j,1,w)MOJ(f[root][0],f[root][j]);
f[root][0]=f[root][0]*P(K,w)%mo;
if(e&1)ans=(ans-f[root][0])%mo;
else ans=(ans+f[root][0])%mo;
return;
}
ss(q+1,w,e);
++e;
if(z[HU[q][0]]&&!z[HU[q][1]])
{
z[HU[q][1]]=z[HU[q][0]];ss(q+1,w,e);
z[HU[q][1]]=0;return;
}
if(z[HU[q][1]]&&!z[HU[q][0]])
{
z[HU[q][0]]=z[HU[q][1]];ss(q+1,w,e);
z[HU[q][0]]=0;return;
}
if(z[HU[q][0]]&&z[HU[q][1]])
{
if(z[HU[q][0]]==z[HU[q][1]])ss(q+1,w,e);
return;
}
if(w<K)z[HU[q][0]]=z[HU[q][1]]=w+1,ss(q+1,w+1,e);
fo(i,1,w)z[HU[q][0]]=z[HU[q][1]]=i,ss(q+1,w,e);
z[HU[q][0]]=z[HU[q][1]]=0;
}
int main()
{
freopen("color.in","r",stdin);
freopen("color.out","w",stdout);
int q,w;
read(n),read(m),read(K);
if(n==m+1)return printf("%lld\n",K*ksm(K-1,n-1)%mo),0;
jc[0]=1;fo(i,1,K)jc[i]=jc[i-1]*i%mo;
jcn[K]=ksm(jc[K],mo-2);fod(i,K-1,0)jcn[i]=jcn[i+1]*(i+1LL)%mo;
fo(i,1,m)read(q),read(w),link(q,w);
dfsh(1,0);
fo(i,1,n)if(Bv[i]==1)d[++d[0]]=i;
LL Ansc=1;
for(;d[0];)
{
q=d[d[0]];--d[0];
z[q]=0;Ansc=Ansc*(K-1LL)%mo;
efo(i,q)if((--Bv[B[i][1]])==1)d[++d[0]]=B[i][1];
}
fo(I,1,n)if(z[I])
{
for(int i=A[I],i1=0;i;i=B[i][0])if(!z[B[i][1]])
{
if(i1)B[i1][0]=B[i][0];
else A[I]=B[i][0];
}else i1=i;
}
fo(i,1,n)if(z[i]){root=i;break;}
fo(i,0,n)z[i]=0;
dfsf(root,0,0);
ans=f[root][0]*K%mo;
fo(I,1,min(K-1,HU0))
{
fo(i,0,I)g[I][0][i][i]=1;
fo(i,1,gmx)
{
fo(k,0,I)g[I][i][0][k]=(LL)g[I][i-1][0][k]*(K-I-1LL)%mo;
fo(j,1,I)fo(k,0,I)MOJ(g[I][i][0][k],g[I][i-1][j][k]);
fo(j,1,I)fo(k,0,I)g[I][i][j][k]=((LL)g[I][i][0][k]+g[I][i-1][0][k]-g[I][i-1][j][k])%mo;
}
}
ss(1,0,0);
ans=ans*Ansc%mo;
printf("%lld\n",(ans+mo)%mo);
return 0;
}