[学习笔记]斯坦纳树
斯坦纳树问题是组合优化问题,与最小生成树相似,是最短网络的一种。最小生成树是在给定的点集和边中寻求最短网络使所有点连通。而最小斯坦纳树允许在给定点外增加额外的点,使生成的最短网络开销最小。
引自百度百科
由于网上的所有解释都不讲人话,因此我结合例题来分析:
给定一个包含
再给定包含
1.
2.
3.
你只需要求出
首先,我们要知道答案子图显然是一棵树,因为如果其上有个环,可以断开环上任意一条边,答案肯定变小。
那么考虑状压
分类讨论:
因此总体时间复杂度是

#include<cstdio> #include<cstring> #include<string> #include<queue> #define int long long #define WR WinterRain using namespace std; const int WR=10010,INF=1099588621776; struct Edge{ int pre,to,val; }edge[WR]; int n,m,k; int p[WR]; int head[WR],tot; int dp[550][2010]; int dis[WR]; bool vis[WR]; queue<int>q; int read(){ int s=0,w=1; char ch=getchar(); while(ch>'9'||ch<'0'){ if(ch=='-') w=-1; ch=getchar(); } while(ch>='0'&&ch<='9'){ s=(s<<1)+(s<<3)+ch-'0'; ch=getchar(); } return s*w; } void add(int u,int v,int val){ edge[++tot].pre=head[u]; edge[tot].to=v; edge[tot].val=val; head[u]=tot; } void SPFA(int S){ while(!q.empty()){ int u=q.front();q.pop(); vis[u]=false; for(int i=head[u];i;i=edge[i].pre){ int v=edge[i].to,val=edge[i].val; if(dp[v][S]>dp[u][S]+val){ dp[v][S]=dp[u][S]+val; if(!vis[v]){ vis[v]=true; q.push(v); } } } } } signed main(){ n=read(),m=read(),k=read(); memset(dp,0x3f,sizeof(dp)); for(int i=1;i<=m;i++){ int u=read(),v=read(),val=read(); add(u,v,val);add(v,u,val); } for(int i=1;i<=k;i++){ p[i]=read();dp[p[i]][1<<(i-1)]=0; } for(int S=0;S<(1<<k);S++){ for(int i=1;i<=n;i++){ for(int S1=(S-1)&S;S1;S1=(S1-1)&S){ dp[i][S]=min(dp[i][S],dp[i][S1]+dp[i][S^S1]); } if(dp[i][S]<=1e9) q.push(i); } SPFA(S); } int ans=INF; for(int i=1;i<=k;i++) ans=min(ans,dp[p[i]][(1<<k)-1]); printf("%lld\n",ans); return 0; }
本文来自博客园,作者:冬天的雨WR,转载请注明原文链接:https://www.cnblogs.com/WintersRain/p/16586402.html
为了一切不改变的理想,为了改变不理想的一切
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现