【CSP-S 2019模拟】T2—仙人球(仙人掌+背包)
感觉主要还是因为没做过仙人掌的题吧
还是很简单的一个背包
把每个环提出来,定一个根
拆环为链
计算不经过根的
否则就肯定是根开始左右分别一段
记录前后缀拼起来
强制一边必须选到某个位置,另一边就是一个前缀和
复杂度
#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
static char ibuf[RLEN],*ib,*ob;
(ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ob==ib)?EOF:*ib++;
}
inline int read(){
char ch=gc();
int res=0,f=1;
while(!isdigit(ch))f^=ch=='-',ch=gc();
while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
#define poly vector<int>
cs int mod=1e9+7;
inline int add(int a,int b){return (a+=b)>=mod?a-mod:a;}
inline int dec(int a,int b){return (a-=b)<0?a+mod:a;}
inline int mul(int a,int b){return 1ll*a*b%mod;}
inline void Add(int &a,int b){(a+=b)>=mod?a-=mod:0;}
inline void Dec(int &a,int b){(a-=b)<0?a+=mod:0;}
inline void Mul(int &a,int b){a=1ll*a*b%mod;}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int N=5005,C=105;
vector<int> e[N];
int f[N][C],pre[N][C],suf[N][C];
int dfn[N],tim,bel[N],cnt,isrt[N];
int n,m,k,vis[N],fa[N],from[N],ans;
vector<int> pt[N];
void tarjan(int u,int fa){
dfn[u]=++tim;
for(int &v:e[u]){
if(v==fa)continue;
if(!dfn[v])from[v]=u,tarjan(v,u);
else if(dfn[v]<dfn[u]){
cnt++,isrt[v]=1,bel[v]=cnt;
for(int x=u;x!=v;x=from[x])bel[x]=cnt,pt[cnt].pb(x);
}
}
}
int tmp[C],tmp2[C];
inline void dp(int *A,int *B,int *C){
for(int x=k;x;x--)
for(int y=1;y<x;y++)Add(A[x],mul(B[y],C[x-y]));
}
inline void calc(int u){
poly now=pt[bel[u]];
int n=now.size()-1;
memcpy(tmp,f[now[0]],sizeof(tmp));
for(int i=1;i<=n;i++)memset(pre[i],0,sizeof(suf[i]));
for(int i=0;i<n;i++)memset(suf[i],0,sizeof(suf[i]));
for(int i=1;i<=n;i++){
memset(tmp2,0,sizeof(tmp2));
dp(tmp2,tmp,f[now[i]]);
memcpy(tmp,tmp2,sizeof(tmp));
for(int x=2;x<=k;x++)Add(ans,tmp[x]);
for(int x=1;x<=k;x++)Add(tmp[x],f[now[i]][x]);
}
memcpy(pre[0],f[now[0]],sizeof(f[now[0]]));
for(int i=1;i<=n;i++)
dp(pre[i],pre[i-1],f[now[i]]);
memcpy(suf[n],f[now[n]],sizeof(f[now[n]]));
for(int i=n-1;~i;i--)
dp(suf[i],suf[i+1],f[now[i]]);
memset(tmp,0,sizeof(int)*(k+1));
for(int i=0;i<=n;i++)
for(int j=1;j<=k;j++)
Add(tmp[j],pre[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=k;j++)
Add(tmp[j],suf[i][j]);
for(int i=1;i<=n;i++)
for(int j=1;j<=k;j++)
Add(pre[i][j],pre[i-1][j]);
for(int i=0;i<=n-2;i++)
dp(tmp,pre[i],suf[i+2]);
dp(f[u],f[u],tmp);
}
inline void getans(int u){
for(int i=1;i<=k;i++)Add(ans,f[u][i]);
}
void dfs(int u){
vis[u]=1,f[u][1]=1;
for(int &v:e[u]){
if(vis[v])continue;
dfs(v);
if(!bel[u]||bel[u]!=bel[v])
dp(f[u],f[u],f[v]);
}
if(isrt[u])calc(u);
getans(u);
}
int main(){
n=read(),m=read(),k=read();
for(int i=1;i<=m;i++){
int u=read(),v=read();
e[u].pb(v),e[v].pb(u);
}
tarjan(1,0);
dfs(1);
cout<<ans<<'\n';
}