题目大意:赤壁决战,曹操在有利形势下,轻敌自负,指挥失误,终致战败。孙权、刘备在强敌进逼关头,结盟抗战,扬水战之长,巧用火攻,终以弱胜强。赤壁之战结束之后魏蜀吴三国决定握手求和,但是因为之前四处交战,把道路全部毁坏了,现在需要重新修路使得三国的国都能够连通.诸葛亮是这个项目的负责人,但是他太聪明了,对于这种题目都懒得思考了,于是就交给你了。
思路:因为要求三个和城市之间的最短路,最短路一定是经过某一点到三点距离和最小,不是一个城市到其他两个城市的最短路。所以3遍spfa把三个城市的最短路跑出来,然后枚举中间点即可。
无法连通输出-1;
#include <iostream> #include <cstdio> #include <string> #include <cstring> #include <fstream> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <vector> #include <map> #include <set> #include <iomanip> using namespace std; //#pragma comment(linker, "/STACK:102400000,102400000") #define maxn 200005 #define MOD 1000000007 #define mem(a , b) memset(a , b , sizeof(a)) #define LL long long #define ULL unsigned long long typedef pair<int , int> pii; const long long INF= 0x3fffffff; int n , m; struct Edge { int u , v , w , next; }edge[maxn]; int head[maxn] , id; int cost1[maxn] , cost2[maxn] , cost3[maxn]; void addedge(int u , int v , int w) { edge[id].u = u; edge[id].v = v; edge[id].w = w; edge[id].next = head[u]; head[u] = id ++; } void spfa(int root , int cost[]) { for(int i = 0 ; i <= n ; i ++) cost[i] = 90000000; cost[root] = 0; queue<int>q; q.push(root); while(!q.empty()) { int u = q.front(); q.pop(); for(int i = head[u] ; i != -1 ; i = edge[i].next) { if(cost[edge[i].v] > cost[u] + edge[i].w) { q.push(edge[i].v); cost[edge[i].v] = cost[u] + edge[i].w; } } } } int main() { int t; scanf("%d" , &t); while(t--) { mem(head , -1); id = 0; scanf("%d %d" , &n , &m); int u ,v , w; for(int i = 0 ; i < m ; i ++) { scanf("%d %d %d" , &u , &v , &w); addedge(u , v , w); addedge(v , u , w); } int a , b , c; scanf("%d %d %d" , &a , &b , &c); spfa(a , cost1); spfa(b , cost2); spfa(c , cost3); long long ans = INF; for(int i = 1 ; i <= n ; i ++) { ans = min(ans , (LL)cost1[i] + cost2[i] + cost3[i]); } if(cost1[b] == cost1[c] && cost1[b] == 90000000 || cost2[a] == cost1[c] && cost2[a] == 90000000 || cost3[b] == cost3[a] && cost3[b] == 90000000) { printf("-1\n"); } else cout << ans << endl; } return 0; }
时间: 2024-10-15 08:57:42