AcWing 1135. 新年好
考察:最短路+dfs
本题的正解思路想到了...但是感觉不可能放弃了....以后要戒掉感觉不可能的这个词
思路:
由于五个点都要到达.当我们从起点到达其中一个点后,剩下的就是求点与点之间的最短距离.这里直接预处理点与点之间的最短距离.再枚举到达点的顺序.不必担心到达某个点的途中去过了另一个点.因为dfs全排列会枚举所有到达点的顺序.当前枚举顺序不一定是正解.
1 #include <iostream> 2 #include <cstring> 3 #include <queue> 4 using namespace std; 5 const int N = 50010,M = 100010,S = 6; 6 typedef pair<int,int> PII; 7 int n,m,a[S],idx,h[N],dist[S][N],path[S+10],ans =0x3f3f3f3f; 8 bool st[N]; 9 struct Road{ 10 int to,ne,w; 11 }road[M<<1]; 12 void add(int a,int b,int w) 13 { 14 road[idx].to = b,road[idx].w = w,road[idx].ne = h[a],h[a] = idx++; 15 } 16 void dijkstra(int s) 17 { 18 priority_queue<PII,vector<PII>,greater<PII> > q; 19 memset(dist[s],0x3f,sizeof dist[s]); 20 memset(st,0,sizeof st); 21 dist[s][a[s]] = 0; 22 q.push({0,a[s]}); 23 while(q.size()) 24 { 25 PII it = q.top(); 26 q.pop(); 27 int u = it.second; 28 if(st[u]) continue; 29 st[u] = 1; 30 for(int i=h[u];~i;i=road[i].ne) 31 { 32 int v = road[i].to; 33 if(dist[s][v]>dist[s][u]+road[i].w) 34 { 35 dist[s][v] = dist[s][u]+road[i].w; 36 q.push({dist[s][v],v}); 37 } 38 } 39 } 40 } 41 void dfs(int cnt) 42 { 43 if(cnt>=5) 44 { 45 int res = dist[0][a[path[0]]]; 46 // for(int i=0;i<5;i++) printf("%d ",a[path[i]]); 47 // printf("\n"); 48 for(int i=0;i<4;i++) 49 res+=dist[path[i]][a[path[i+1]]]; 50 ans = min(res,ans); 51 return; 52 } 53 for(int i=1;i<=5;i++) 54 if(!st[i]) 55 { 56 path[cnt] = i; 57 st[i] = 1; 58 dfs(cnt+1); 59 st[i] = 0; 60 } 61 } 62 int main() 63 { 64 scanf("%d%d",&n,&m); 65 memset(h,-1,sizeof h); 66 a[0] = 1; 67 for(int i=1;i<=5;i++) scanf("%d",&a[i]); 68 while(m--) 69 { 70 int a,b,w; scanf("%d%d%d",&a,&b,&w); 71 add(a,b,w); add(b,a,w); 72 } 73 for(int i=0;i<=5;i++) dijkstra(i); 74 memset(st,0,sizeof st); 75 dfs(0); 76 printf("%d\n",ans); 77 return 0; 78 }