m ≤ n + 5 , k , n ≤ 1 0 5 m\leq n+5,k,n\leq10^5 m≤n+5,k,n≤105
这个图只有5条返祖边所以才能做,
先把所有有返祖边的点拿出来,(姑且叫做返祖点)
自然地,考虑容斥,枚举一条返祖边的两个点是否同色,以及返祖边点之间的染色情况,
枚举后DP计算,设 f x , i f_{x,i} fx,i表示点x染颜色i时的方案数,注意颜色0表示其他颜色,即没有被枚举的颜色,
因为有6条返祖边,所以染色情况最多877种(贝尔数),每次DP至少需要O(n)时间,过不了考虑优化,
显然的,所有度数为1的点都可以删掉,他们对ans的贡献恒为(K-1),
删完以后再把链缩一下就是返祖点构成的虚树了,
缩链简单,像矩阵乘法那样弄就好了,
这样每次DP的复杂度就很小了,直接在虚树上跑即可,
复杂度: O ( k 3 n + 2 B k k ) O(k^3n+2B_kk) O(k3n+2Bkk)
(前面的预处理+后面的枚举及DP)
先转化一下,
原图的每条边都有两个值(a,b),分别表示如果两个点同色的贡献和不同色的贡献,
对于一种染色方案,答案为所有边的贡献乘起来,
显然的,对于原图,每条边的值为(0,1),
考虑缩点,
显然的叶子可以直接缩点,他们对ans的贡献恒为(K-1),
对于度数为2的点,可以通过以下方式缩掉:
设点 u u u数为2,它连向的两个点为 v 1 , v 2 v_1,v_2 v1,v2,边 ( u , v 1 ) (u,v_1) (u,v1)的值为 ( a 1 , b 1 ) (a_1,b_1) (a1,b1),边 ( u , v 2 ) (u,v_2) (u,v2)的值为 ( a 2 , b 2 ) (a_2,b_2) (a2,b2),
删去点 u u u以及其连出去的边,
添加边 ( v 1 , v 2 ) (v_1,v_2) (v1,v2),其值为 ( a 1 a 2 + b 1 b 2 ( K − 1 ) , a 1 b 2 + b 1 a 2 + b 1 b 2 ( K − 2 ) ) (a_1a_2+b_1b_2(K-1),a_1b_2+b_1a_2+b_1b_2(K-2)) (a1a2+b1b2(K−1),a1b2+b1a2+b1b2(K−2))
这样不停的缩点,最后最多只会剩下10个点15条边,
这么小暴力即可,跑个状压DP子集转移之类的即可
#include
#include
#include
#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;
}