首页 > 代码库 > 斯坦纳树模板
斯坦纳树模板
屌炸天阿什么东西都有 丢
//斯坦纳树模板 让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 longconst 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;}
斯坦纳树模板
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。