題目大意:給你1~N的城市和城市之間的距離,且均爲雙向邊,兩個城市之間至多隻能有一條邊,求城市1到城市2之間的距離。同時有一條件,給出每個城市的陣營,不同陣營之間的路最多隻能走一條。其中城市1只能爲陣營1,城市2只能爲陣營2。
思路:最大的問題在於不同陣營之間的路最多隻能走一條,而Mr.M在起點城市1,到終點城市2,那麼轉化爲從陣營1去了陣營2就回不來了,再抽象一下就是隻能從陣營1到陣營2,不能從陣營2到陣營1,這不就是有向邊的特徵嗎。。
所以對於連接不同陣營的邊,轉化爲陣營1到陣營2的有向邊即可。
還要注意兩個城市之間至多隻能有一條邊,也就是所有邊中選出權值最小的邊,不得不說去重這種事還是鄰接矩陣比較方便。最後再輸入鄰接表解決雙向變單項問題。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <map>
#include <climits>
using namespace std;
const int MAXN = 605;
const int INF = INT_MAX;
struct Edge{
int to;
int length;
Edge(int t, int l): to(t), length(l) {}
};
struct Point{
int number;
int distance;
Point(int n, int d): number(n), distance(d) {}
bool operator< (const Point& c) const {
return distance > c.distance;
}
};
int N, team[MAXN], dis[MAXN];
bool visit[MAXN];
int judge[MAXN][MAXN];
vector<Edge> graph[MAXN];
void Initial(){
for(int i = 1; i <= N; i++){
graph[i].clear();
}
fill(dis + 1, dis + N + 1, INF);
memset(visit, false, sizeof(visit));
memset(judge, 0, sizeof(judge));
}
void Dijkstra(int start){
dis[start] = 0;
priority_queue<Point> myqueue;
myqueue.push(Point(start, dis[start]));
while(!myqueue.empty()){
int from = myqueue.top().number;
myqueue.pop();
if(visit[from]) continue;
visit[from] = true;
for(int i = 0; i < graph[from].size(); i++){
int to = graph[from][i].to;
int d = graph[from][i].length;
if(dis[from] + d < dis[to]){
dis[to] = dis[from] + d;
myqueue.push(Point(to, dis[to]));
}
}
}
return;
}
int main(){
// freopen("in.txt", "r", stdin);
int M, A, B, T;
while(~scanf("%d", &N)){
if(N == 0) break;
Initial();
scanf("%d", &M);
for(int i = 0; i < M; i++){//輸入解決重邊最小值問題
scanf("%d %d %d", &A, &B, &T);
if(judge[A][B] == 0) judge[A][B] = T;
else judge[A][B] = min(judge[A][B], T);
if(judge[B][A] == 0) judge[B][A] = T;
else judge[B][A] = min(judge[B][A], T);
}
for(int i = 1; i <= N; i++){
scanf("%d", &team[i]);
}
for(int i = 1; i <= N; i++){//鄰接表部分解決雙向邊變單向邊
for(int j = 1; j <= N; j++){
if(team[i] == 2 && team[j] == 1) continue;
if(judge[i][j] != 0) graph[i].push_back(Edge(j, judge[i][j]));
}
}
Dijkstra(1);
if(dis[2] == INF) printf("-1\n");
else printf("%d\n", dis[2]);
}
return 0;
}