2018 Multi-University Training Contest 7--Age of Moyu--hdu--6386

Age of Moyu

Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
Total Submission(s): 2178    Accepted Submission(s): 673

 

Problem Description

Mr.Quin love fishes so much and Mr.Quin’s city has a nautical system,consisiting of N ports and M shipping lines. The ports are numbered 1 to N. Each line is occupied by a Weitian. Each Weitian has an identification number.

The i-th (1≤i≤M) line connects port Ai and Bi (Ai≠Bi) bidirectionally, and occupied by Ci Weitian (At most one line between two ports).

When Mr.Quin only uses lines that are occupied by the same Weitian, the cost is 1 XiangXiangJi. Whenever Mr.Quin changes to a line that is occupied by a different Weitian from the current line, Mr.Quin is charged an additional cost of 1 XiangXiangJi. In a case where Mr.Quin changed from some Weitian A's line to another Weitian's line changes to Weitian A's line again, the additional cost is incurred again.

Mr.Quin is now at port 1 and wants to travel to port N where live many fishes. Find the minimum required XiangXiangJi (If Mr.Quin can’t travel to port N, print −1instead)

Input

There might be multiple test cases, no more than 20. You need to read till the end of input.

For each test case,In the first line, two integers N (2≤N≤100000) and M (0≤M≤200000), representing the number of ports and shipping lines in the city.

In the following m lines, each contain three integers, the first and second representing two ends Ai and Bi of a shipping line (1≤Ai,Bi≤N) and the third representing the identification number Ci (1≤Ci≤1000000) of Weitian who occupies this shipping line.

Output

For each test case output the minimum required cost. If Mr.Quin can’t travel to port N, output −1 instead.

Sample Input

3 3

1 2 1

1 3 2

2 3 1

2 0

3 2

1 2 1

2 3 2

Sample Output

1

-1

2

Source

2018 Multi-University Training Contest 7

题意:

给你n个点与m条边,想需要从1到n,每个点可能由不同的公司运营,当你切换道路时,花费需要+1,然后让你求最小花费,如不能到底n,就输出-1.

题解:

别看题面花哨,就计算切换不同公司运营路线次数+1就好,但是不能直接跑Dijkstra,会直接TLE,要加个堆优化,或者用优先队列应该能过,这里使用集合记录点,使用优先队列优化的bfs计算花费。

算法:

bfs,前向星。

这里正好学习了一下前向星,懵懵懂懂的,还是不会用啊T.T。

前向星:一般来讲,图的常用存储结构有邻接矩阵,和邻接表,但我们知道邻接矩阵空间浪费太严重,邻接表不好写,今天来讲一下图的另一只常用的存储结构:前向星和链式前向星,介于上述两种存储结构之间的一种比较均衡的存储结构。创造人:https://malash.me/200910/linked-forward-star/

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 +10;
const int inf = 0x3f3f3f3f;
int n,m,k,t,h[N],tot;
int num[N],ans[N];
struct owo {
	int v,id,next;
} edges[N<<2];
int head[N];
int dis[N];
set<int> sta[N];

void init() {
	tot = 0;
	memset(head,-1,sizeof(head));
}

void add(int u,int v,int id) {//前向星 
	edges[tot] = (owo) { //初始化,将结构体owo初始化给edge;
		v,id,head[u]
	};
	head[u] = tot++;
}

struct Node {
	int val,u;
	int pre,fa;
	bool operator <(const Node &p)const {//优先队列重载< 
		return val>p.val;
	}
};

void bfs(int s,int t) {
	memset(dis,inf,sizeof(dis));
	dis[s] = 0;
	priority_queue<Node> q;
	q.push((Node){//放入起点 
		dis[s],s,-1,-1
	});
	while(!q.empty()) {
		Node temp = q.top();
		q.pop();
		int pre = temp.pre;
		int u = temp.u;
		if(temp.val>dis[u])continue;
		else if(temp.val == dis[u]) {
			bool tip = true;
			if(sta[u].find(pre)!=sta[u].end())
				continue;
			sta[u].insert(pre);
		} else {
			dis[u] = temp.val;
			sta[u].clear();
			sta[u].insert(pre);
		}
		for(int i = head[u]; ~i; i = edges[i].next) {
			int v = edges[i].v,now = edges[i].id;
			if(v == temp.fa)continue;
			if((dis[u]+(pre!=now))<=dis[v]) {
				dis[v] = dis[u] + (pre!=now);
				if(v!=t)q.push((Node) {
					dis[v],v,now,temp.u
				});
			}
		}

	}
}
int main() {
#ifndef ONLINE_JUDGE //输入输出挂 
	freopen("in.txt","r",stdin);
	freopen("out.txt","w",stdout);
#endif
	int n,m;
	int u,v,id;
	while(scanf("%d%d",&n,&m)==2) {
		for(int i=1; i<=n; ++i) sta[i].clear();
		init();
		while(m--) {
			scanf("%d%d%d",&u,&v,&id);
			add(u,v,id);//双向边 
			add(v,u,id);
		}
		bfs(1,N);//起点终点 
		if(dis[n]==inf) dis[n]=-1;
		printf("%d\n",dis[n]);
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值