题意:给你一个图,并告诉你只能走那些点,问你从0走完这S个点在回去的最短路是多少
思路:首先预处理出从这S+1个点(0和S个点)两两到达的距离,之后就是一发裸的状压就好了
上代码:
#include <bits/stdc++.h> using namespace std; const int maxn = 100000+10; const int INF = 9999999; struct node { int to,nex,val; }edg[maxn<<1]; int n,m,cnt; int head[maxn],dis[maxn],vis[maxn]; int DIS[12][12]; int rode[maxn],dp[1<<11][11]; void init() { cnt = 0 ; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { edg[cnt].to = v; edg[cnt].val = w; edg[cnt].nex = head[u]; head[u] = cnt++; } int SPFA(int s,int e) { for(int i = 0 ; i < n ; i++) { dis[i] = INF; vis[i] = 0; } queue<int>que; while(!que.empty()) que.pop(); que.push(s); dis[s] = 0; while(!que.empty()) { int u = que.front(); que.pop(); vis[u] = 0; for(int i = head[u] ; i != -1 ; i = edg[i].nex) { int v = edg[i].to; int w = edg[i].val; if(dis[v] > dis[u] + w) { dis[v] = dis[u] + w; if(!vis[v]){ vis[v] = 1; que.push(v); } } } } return dis[e]; } int main() { int t; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); memset(DIS,0,sizeof(DIS)); init(); int a,b,c; for(int i = 0 ; i < m ; i++) { scanf("%d%d%d",&a,&b,&c); add(a,b,c); add(b,a,c); } for(int i = 0 ; i < n ; i++) { for(int j = head[i] ; j!= -1 ; j = edg[j].nex) { int v = edg[j].to; int w = edg[j].val; } } int te; scanf("%d",&te); for(int i = 1 ; i <= te ; i ++) { scanf("%d",&rode[i]); } for(int i = 1 ; i <= te ; i++) { DIS[0][i] = DIS[i][0] = SPFA(0,rode[i]); } for(int i = 1 ; i <= te ; i ++) { for(int j = i + 1 ; j <= te ; j++) { DIS[i][j] = DIS[j][i] = SPFA(rode[i],rode[j]); } } /* for(int i = 0 ; i <= te ; i++) { for(int j = 0 ; j <= te ; j ++) { printf("%d ",DIS[i][j]); } puts(""); }*/ te++; for(int i = 0 ; i < (1<<te) ; i++) { for(int j = 0 ; j < te ; j ++) dp[i][j] = INF; } dp[0][0] = 0; for(int state = 0 ; state < (1<<te) ; state++) { for(int i = 0 ; i < te ; i ++) { if(dp[state][i] == INF) continue; for(int j = 0 ; j < te ; j++) { if((1<<j)&state) continue; if(DIS[i][j] == INF) continue; dp[(1<<j)|state][j] = min(dp[(1<<j)|state][j] , dp[state][i] + DIS[i][j]); } } } int ans = INF; for(int i = 0 ;i < te ; i++) { // printf("%d %d\n",dp[(1<<te)-1][i] , DIS[i][0]); ans = min(ans,dp[(1<<te)-1][i] + DIS[i][0]); } printf("%d\n",ans); } return 0; }