题解:P6192 【模板】最小斯坦纳树
include13_fAKe · · 题解
偶然看到这题还能提交题解来水一发
之前 ABC 的 G 题经常出这个啊,但我不会就白搭了吗。
令
对每一个新的结果都要跑一遍 dijkstra,我的时间复杂度为
为啥我代码没有火车头都能写得到 2.65K?ZYN 1.08K 结束了。并且他的代码的评测用时之和比我的最慢点还快一倍以上?
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=107;
const int M=5005;
int n,m,k;
int zdl[N][N];
int vis[N][N];
int dp[N][M]; //dp[i][j] 表示整个集合 j 整合在 i 号点上
int pow2[20],pow3[20];
int point[20];
int point1[N];
vector<pair<int,int> > g[N];
void init(){
memset(zdl,0x3f,sizeof(zdl));
memset(point1,-1,sizeof(point1));
memset(dp,0x3f,sizeof(dp));
pow2[0]=pow3[0]=1;
for(int i=1;i<=17;i++){
pow2[i]=pow2[i-1]*2,pow3[i]=pow3[i-1]*3;
}
}
void dijkstra(int st){
priority_queue<pair<int,int> > q;
q.push(make_pair(0,st));
while(!q.empty()){
int now1=q.top().second,now2=-q.top().first;
q.pop();
if(vis[st][now1]) continue;
vis[st][now1]=1;
for(int i=0;i<g[now1].size();i++){
int v=g[now1][i].first,w=g[now1][i].second;
if(zdl[st][v]>zdl[st][now1]+w){
zdl[st][v]=zdl[st][now1]+w;
q.push(make_pair(-zdl[st][v],v));
}
}
}
if(~point1[st]){
int bitplace=pow2[point1[st]];
if(!bitplace) return;
for(int i=1;i<=n;i++){
//这里枚举停留在哪个点
dp[i][bitplace]=zdl[st][i];
// cout<<i<<' '<<bitplace<<' '<<dp[i][bitplace]<<endl;
}
}
}
int vis1[107];
void dijkstra2(int zt){
priority_queue<pair<int,int> > q;
//这里是对 dp[停留位置][zt] 进行转移
for(int i=1;i<=n;i++){
q.push(make_pair(-dp[i][zt],i));
vis1[i]=0;
}
while(!q.empty()){
int now1=q.top().second;
q.pop();
if(vis1[now1]) continue;
vis1[now1]=1;
for(int i=0;i<g[now1].size();i++){
int v=g[now1][i].first,w=g[now1][i].second;
if(dp[v][zt]>dp[now1][zt]+w){
dp[v][zt]=dp[now1][zt]+w;
q.push(make_pair(-dp[v][zt],v));
}
}
}
}
signed main(){
init();
cin>>n>>m>>k;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
g[u].push_back(make_pair(v,w)),g[v].push_back(make_pair(u,w));
}
for(int i=0;i<k;i++){
cin>>point[i],point1[point[i]]=i;
}//全局中只有 point1 使用 0 开始排序
for(int i=1;i<=n;i++){
zdl[i][i]=0;
dijkstra(i);
}
// cout<<dp[1][1]<<endl;
for(int i=1;i<pow3[k];i++){
//三进制状压枚举子集
int x1=0,x2=0; //代表两个子集的具体情况
int nowi=i;
for(int j=0;j<k;j++){
if(nowi%3==1) x1+=pow2[j];
else if(nowi%3==2) x2+=pow2[j];
nowi/=3;
for(int l=1;l<=n;l++){
dp[l][x1|x2]=min(dp[l][x1|x2],dp[l][x1]+dp[l][x2]);
}
// cout<<x1<<' '<<x2<<endl;
}
dijkstra2(x1|x2);
// for(int j=1;j<=n;j++){
// dp[j][x1|x2]=min(dp[j][x1|x2],dp[j][x1]+dp[j][x2]);
// cout<<j<<' '<<(x1|x2)<<' '<<dp[j][x1|x2]<<endl;
// }
}
int include13=1e18;
for(int i=1;i<=n;i++){
include13=min(include13,dp[i][pow2[k]-1]);
}
cout<<include13<<endl;
// cout<<dp[6][15]<<endl;
return 0;
}