斯坦纳树模板

屌炸天阿什么东西都有 丢

//斯坦纳树模板 让k个点联通的最小生成树 复杂度 n*3^k 
#include<iostream>
#include<cstring>
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<deque>
#include<list>
#include<algorithm>
#include<stdio.h>
#include<iomanip>

#define rep(i,n) for(int i=0;i<n;++i)
#define fab(i,a,b) for(int i=a;i<=b;++i)
#define fba(i,b,a) for(int i=b;i>=a;--i)
#define PB push_back
#define INF 0x3f3f3f3f
#define MP make_pair
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define sf scanf
#define pf printf
#define LL long long
const int N=55;
using namespace std;
typedef pair<int,int>PII;
int n,m,k;
queue<int>Q;
int dp[N][1<<10],st[N],all;
bool  vis[N][1<<10];
int dpans[1<<10];
const int M =10010;
int head[N];
int to[M],next[M],cost[M];
int e;
void init(){
    memset(head,-1,sizeof head);
    while(!Q.empty())Q.pop();
    e=0;
}
void addedge(int u,int v,int w){
    to[e]=v;
    cost[e]=w;
    next[e]=head[u];
    head[u]=e++;
}
void input(){
    sf("%d%d%d",&n,&m,&k);
    rep(i,m){
        int u,v,w;
        sf("%d%d%d",&u,&v,&w);
        u--;v--;
        addedge(u,v,w);
        addedge(v,u,w);
    }
}
void stma_init(){
    all=(1<<(2*k));
    rep(i,n)rep(j,all)dp[i][j]=INF;
    memset(st,0,sizeof st);
    memset(vis,0,sizeof vis);
    rep(i,k){
        st[i]=(1<<i);
        st[n-k+i]= (1<<(i+k));
        dp[i][st[i]]=0;
        dp[n-k+i][st[n-k+i]]=0;
    }
}

void spfa(int state){
    while(!Q.empty()){
        int u=Q.front();Q.pop();
        vis[u][state]=false;
        for(int p=head[u];~p;p=next[p]){
            int v=to[p];
            int w=cost[p];
            if(dp[v][st[v]|state]>dp[u][state]+w){
                dp[v][st[v]|state]=dp[u][state]+w;
                if(st[v]|state!=state||vis[v][state])continue;
                vis[v][state]=1;
                Q.push(v);
            }
        }
    }
}
void STMA(){
    stma_init();
    for(int j=1;j<all;j++){
        rep(i,n){
           if(st[i]&&(st[i]&j)==0)continue;
           for(int sub=(j-1)&j;sub;sub=(sub-1)&j){
               int x=st[i]|sub,y=st[i]|(j-sub);
               dp[i][j]=min(dp[i][j],dp[i][x]+dp[i][y]);
           }
           if(dp[i][j]<INF){
               Q.push(i);
               vis[i][j]=true;
           }
        }
        spfa(j);
    }
}
/*
void spfa(){
    while(!Q.empty()){
        int j=Q.front()/1200;
        int i=Q.front()%1200;
        Q.pop();
        vis[j][i]=0;
        for(int p=head[j];~p;p=next[p]){
            int v=to[p],w=cost[p];
            int nxt=i|st[v];
            if(dp[j][i]+w<dp[v][nxt]){
                dp[v][nxt]=dp[j][i]+w;
                if(nxt==i&&!vis[v][nxt]){
                    vis[v][nxt]=1;
                    Q.push(v*1200+nxt);
                }
            }
        }
    }
}
void STMA(){
    stma_init();
    rep(i,all){
        rep(j,n){
            for(int t=(i-1)&i;t;t=(t-1)&i){
                dp[j][i]=min(dp[j][i],dp[j][t|st[j]]+dp[j][(i-t)|st[j]]);
            }
            if(dp[j][i]<INF){
                Q.push(j*1200+i);
                vis[j][i]=1;
            }
        }
        spfa();
    }
}*/
bool check(int s){
    int cnt=0;
    rep(i,k){
        if(s&(1<<i))cnt++;
        if(s&(1<<(k+i)))cnt--;
    }
    return cnt==0;
}
void bug(){
    puts("bug");
    pf("%d\n",all);
    rep(i,all)pf("%d ",dpans[i]);
}
void solve(){
   STMA();//模板,求出来的是一颗树


   //因为这道题的解可能是森林,所以要对求出来的东东再进行dp
   rep(i,all){
      dpans[i]=INF;
      rep(j,n)dpans[i]=min(dpans[i],dp[j][i]);
   }
   for(int i=1;i<all;i++){
       if(check(i)){
           for(int j=(i-1)&i;j;j=(j-1)&i){
               if(check(j))dpans[i]=min(dpans[i],dpans[j]+dpans[i-j]);
           }
       }
   }
   if(dpans[all-1]<INF)pf("%d\n",dpans[all-1]);
   else puts("No solution");
}
int main(){
    int T;sf("%d",&T);
    while(T--){
        init();
        input();
        solve();
    }
    return 0;
}

 

posted on 2014-11-29 00:32  wanggp3  阅读(207)  评论(0编辑  收藏  举报

导航