牛客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;
}
发布了411 篇原创文章 · 获赞 72 · 访问量 16万+

猜你喜欢

转载自blog.csdn.net/Flynn_curry/article/details/105414552