求无向图中连通指定的k个节点的最小代价(斯坦纳树)

题:https://www.luogu.com.cn/problem/P6192

题意:求最小斯坦纳树

分析:答案一定是树,因为有环的话,可以删除成环边让答案更小;

   dp[i][s],表示以 i 为根,状态为s的最小代价,枚举子集和补集来dp,用最短路把每个S松弛一下

#include<bits/stdc++.h>
using namespace std;
#define pb push_back
#define MP make_pair
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
typedef long long ll;
const int mod=1e9+7;
const int M=1e4+6;
const int inf=0x3f3f3f3f;
const ll INF=1e18;
int dp[102][M];
struct qnode{
    int v;
    ll c;
    qnode(int _v=0,ll _c=0):v(_v),c(_c){}
    bool operator <(const qnode &r)const{
     return c>r.c;
    }
};
struct Edge{
    int v;
    ll cost;
    Edge(int _v=0,ll _cost=0):v(_v),cost(_cost){}
};
vector<Edge>E[M];
bool vis[M];
priority_queue<qnode>que;
void Dij(int cursta){
    memset(vis,false,sizeof(vis));
    qnode tmp;
    while(!que.empty()){
        tmp=que.top();
        que.pop();
        int u=tmp.v;
        if(vis[u])continue;
            vis[u]=true;
        for(int i=0;i<E[u].size();i++){
            int v=E[tmp.v][i].v;
            int cost=E[u][i].cost;
            if(!vis[v]&&dp[v][cursta]>dp[u][cursta]+cost){
                dp[v][cursta]=dp[u][cursta]+cost;
                que.push(qnode(v,dp[v][cursta]));
            }
        }
    }
}
void addedge(int u,int v,ll w){
    E[u].push_back(Edge(v,w));
}
int p[M];
int main(){
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    for(int u,v,w,i=1;i<=m;i++){
        scanf("%d%d%d",&u,&v,&w);
        addedge(u,v,w);
        addedge(v,u,w);
    }
    memset(dp,0x3f,sizeof(dp));
    int limit=dp[0][0];
    for(int i=1;i<=k;i++){
        scanf("%d",&p[i]);
        dp[p[i]][1<<(i-1)]=0;
    }
    for(int s=1;s<(1<<k);s++){
        for(int i=1;i<=n;i++){
            for(int sta=s&(s-1);sta;sta=s&(sta-1))///枚举子集
                dp[i][s]=min(dp[i][s],dp[i][sta]+dp[i][s^sta]);
            if(dp[i][s]<limit)
                que.push(qnode(i,dp[i][s]));
        }
        Dij(s);
    }
    printf("%d\n",dp[p[1]][(1<<k)-1]);///因为是要连通起k个指定节点,所以每个dp[p[i]]都是最小的,所以随便取一个
    return 0;
}
View Code

 

posted @ 2020-10-10 10:54  starve_to_death  阅读(257)  评论(0编辑  收藏  举报