Description
给你一个n个点m条边的图,求不同的斯坦纳树的个数,
1 ≤ n ≤ 50 , K ( 关 键 点 ) ≤ 12 1\leq n \leq 50,K(关键点)\leq 12 1≤n≤50,K(关键点)≤12
Solution
老年人复习题,
将DP分成两类:f,g,分别表示 限制一定为链的 和 无限制的 答案,
如何不重不漏枚举子集:
强制选最高位为f,剩下的为g,这样就OK了
Code
#include <bits/stdc++.h>
#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 sqr(q) ((q)*(q))
using namespace std;
typedef long long LL;
typedef double db;
typedef pair<int,int> pii;
const int N=60,M=8200,mo=1e9+7,INF=mo+1;
int read(int &n)
{
bool q=0;n=0;char ch=' ';
for(;ch!='-'&&(ch<'0'||ch>'9');ch=getchar());
if(ch=='-')ch=getchar(),q=1;
for(;ch>='0'&&ch<='9';ch=getchar())n=(n<<3)+(n<<1)+ch-48;
return q?n=-n:n;
}
unsigned seed = std::chrono::system_clock::now().time_since_epoch().count();
mt19937 rand_num(seed); // 大随机数
uniform_int_distribution<int> dist(0, 1000000000);
int RD(int q){return rand_num()%q;}
int n,m,K;
vector<int>B[N];
int zx[N];
int er[N];
void link(int q,int w)
{
B[q].push_back(w);
B[w].push_back(q);
}
struct Val
{
int v;
LL cnt;
Val(int q=INF,LL w=0):v(q),cnt(w){}
void MIN(Val q)
{
if(q.v>v)return;
if(q.v<v)
{
v=q.v;
cnt=q.cnt;
}else cnt=(cnt+q.cnt)%mo;
}
friend Val operator+(Val q,Val w){return Val(q.v+w.v,q.cnt*w.cnt%mo);}
}f[N][M],g[N][M];
Val dis[N];
vector<int>d[N];
void BFS()
{
fo(i,1,n)if(dis[i].cnt && dis[i].v<n)
{
d[dis[i].v].push_back(i);
}
fo(I,1,n)
{
for(int q:d[I])if(dis[q].v==I)
{
for(int w:B[q])
{
if(dis[w].v>I+1)d[I+1].push_back(w);
dis[w].MIN(dis[q]+Val(1,1));
}
}
d[I].clear();
}
}
void steiner()
{
fo(i,1,n)
{
fo(j,0,er[K+1]-1)f[i][j]=g[i][j]=Val();
g[i][0]=Val(0,1);
}
fo(I,1,er[K+1]-1)
{
fo(i,1,n)dis[i]=Val();
fo(i,1,n)
{
if(er[zx[i]]&I)
{
g[i][I]=g[i][I^er[zx[i]]];
}else
{
for(int j=I;j>I-j;j=(j-1)&I)
{
g[i][I].MIN(f[i][j]+g[i][(I-j)]);
}
}
for(int w:B[i])
dis[w].MIN(g[i][I]+Val(1,1));
}
BFS();
fo(i,1,n)f[i][I].MIN(dis[i]),g[i][I].MIN(f[i][I]);
}
}
int main()
{
int q,w,e;
er[1]=1;fo(i,2,15)er[i]=er[i-1]<<1;
while(scanf("%d%d%d",&n,&m,&K)!=EOF)
{
fo(i,1,m)read(q),read(w),link(q,w);
fo(i,1,K)zx[i]=i;
fo(i,K+1,n)zx[i]=0;
steiner();
printf("%d ",g[1][er[K+1]-1].v);
printf("%lld\n",g[1][er[K+1]-1].cnt);
fo(i,1,n)B[i].clear(),zx[i]=0;
}
return 0;
}