题解 P6192【【模板】最小斯坦纳树】
题意
给出一张
考虑其与
再考虑用
这部分时间复杂度是
- 若
i 的度数大于1
考虑
这里简单说明一下枚举子集的时间复杂度:
所以这部分时间复杂度是
总时间复杂度就是
另外,满足题目要求的树为斯坦纳树,这个算法构建出来的树被称为最小斯坦纳树。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
namespace IO{//by cyffff
}
const int N=100+10,K=10;
int n,m,k,p[N],up;
int cnt,head[N];
int dp[N][1<<K];
struct Edge{
int to,nxt,w;
}a[N*10];
inline void add(int u,int v,int w){
cnt++;
a[cnt].to=v;
a[cnt].w=w;
a[cnt].nxt=head[u];
head[u]=cnt;
}
queue<int>q;
bool vis[N];
inline void SPFA(int s){
while(!q.empty()){
int rt=q.front();
q.pop();
vis[rt]=0;
for(int i=head[rt];i;i=a[i].nxt){
int t=a[i].to;
if(dp[t][s]>dp[rt][s]+a[i].w){
dp[t][s]=dp[rt][s]+a[i].w;
if(!vis[t])
q.push(t),vis[t]=1;
}
}
}
}
int main(){
memset(dp,127/3,sizeof(dp));
n=read(),m=read(),k=read();
for(int i=1;i<=m;i++){
int u=read(),v=read(),w=read();
add(u,v,w),add(v,u,w);
}
for(int i=1;i<=k;i++){
p[i]=read();
dp[p[i]][1<<i-1]=0;
}
up=(1<<k)-1;
for(int s1=0;s1<=up;s1++){
for(int i=1;i<=n;i++){
for(int s2=s1&s1-1;s2;s2=s2-1&s1)
dp[i][s1]=min(dp[i][s1],dp[i][s2]+dp[i][s1^s2]);
if(dp[i][s1]<1e9)
q.push(i),vis[i]=1;
}
SPFA(s1);
}
write(dp[p[1]][up]);
flush();
}
再见 qwq~