牛客oj 習題11.7||poj 3767 I Wanna Go Home(最短路+有向邊處理)

 

題目鏈接:https://www.nowcoder.com/practice/0160bab3ce5d4ae0bb99dc605601e971?tpId=40&tqId=21359&tPage=1&rp=1&ru=/ta/kaoyan&qru=/ta/kaoyan/question-ranking

 

題目大意:給你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;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章