點仙人掌(cactus)
阿新 • • 發佈:2018-10-31
時間限制: 1 Sec 記憶體限制: 512 MB
題解:
的暴力,在樹上做樹形
。
#include<cstdio>
#include <algorithm>
#include<vector>
using namespace std;
const int mod=1e9+7,N=1e6+5;
int cnt,id,belong[N],n,m,top,K,ans,ti,head[N],dfn[N],low[N];
int stack[N],instack[N],S[10005][31],F[10005][31],A[N],B[35];
vector<int> vec[N];
struct node
{
int vet,next;
}edge[N];
void add(int u,int v)
{
edge[ ++cnt].vet=v;
edge[cnt].next=head[u];
head[u]=cnt;
}
void Tarjan(int x,int fa)
{
dfn[x]=low[x]=++ti;
stack[++top]=x;
instack[x]=1;
for(int i=head[x];i;i=edge[i].next)
{
int V=edge[i].vet;
if(V==fa)continue;
if(!dfn[V])
{
Tarjan(V,x);
low[x]=min(low[x],low[V]);
}else if(instack[V])
low[x]=min(low[x],dfn[V]);
}
if(low[x]==dfn[x])
{
int u=-1;
id++;
while(u!=x)
{
u=stack[top--];
vec[id].push_back(u);
belong[u]=id;
instack[u]=0;
}
}
}
void solve(int x,int fa,int ST)
{
int st=0;
for(int cas=0;cas<vec[x].size();cas++)
{
int now=vec[x][cas];
if(now==ST)st=cas;
S[now][1]=1;
for(int i=head[now];i;i=edge[i].next)
{
int V=edge[i].vet;
if(belong[V]==fa||belong[now]==belong[V])continue;
solve(belong[V],x,V);
for(int X=K;X>=1;X--)
for(int Y=1;Y<X;Y++)
(S[now][X]+=1ll*S[now][X-Y]*F[V][Y]%mod)%=mod;
}
}
int len=(int)vec[x].size();
for(int cas=0;cas<len;cas++)stack[cas]=vec[x][cas];
int tag=0;
for(int X=1;X<=K;X++)F[ST][X]=S[ST][X];
for(int i=0;i<len;i++)
{
for(int j=1;j<=K;j++)A[j]=S[stack[i]][j],(ans+=A[j])%=mod;
int FF=(i==st);
int ss=1;
for(int j=(i+1)%len;j!=i;j=(j+1)%len)
{
if((j+1)%len==i)
{
if(tag)break;
tag=1;
}
if(j==st)FF=1;
int now=stack[j];
for(int X=1;X<=K;X++)B[X]=0;
for(int X=K;X>=1;X--)
for(int Y=1;Y<X;Y++)
(B[X]+=1ll*A[X-Y]*S[now][Y]%mod)%=mod;
for(int X=1;X<=K;X++)A[X]=B[X],(ans+=A[X])%=mod;
int flag=0;
for(int X=1;X<=K;X++)if(A[X])flag=1;
if(!flag)break;
if(FF)for(int X=1;X<=K;X++)(F[ST][X]+=A[X])%=mod;
ss++;
if(ss>K)break;
}
}
}
int main()
{
scanf("%d%d%d",&n,&m,&K);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
add(u,v);add(v,u);
}
Tarjan(1,0);
solve(belong[1],0,1);
printf("%d\n",ans);
return 0;
}