HDU 6386 Age of Moyu 【BFS+DFS】(2018 MUTC 7)

Age of Moyu

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


 

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

 题目大意:

给你n和m,代表有n个港口,还有m条航线。每条航线上都被其中一家公司承包了。假设你最开始走的是1号公司的航线,你要支付1块钱,但是当你下次还是走1公司的航线的时候,就不需要给钱了;如果你走的不是1公司的,是3公司的,那么就要重新给1块钱。

解法:

根据题意,给出的m条航线是双向边,也就是无向图,我们要建两次边,也就是说假设有a->b航线,那么我们还要反着建一条航线b->a。然后跑一遍bfs,相同航线的去dfs寻找,不行的就可以换一条航线去寻找。因为是以bfs为基础去dfs,所以找到的就是需要最少交换航线公司的次数。(弱鸡自闭了一下午,看了大佬的代码才能写出来,嘤嘤嘤~)

#include <bits/stdc++.h>
#include <queue>
#define MAXN 100005
using namespace std;
struct KNIGHT{
	int a,b,c,next;
	bool vis;//判断是否访问过 
}p[MAXN << 2];

int head[MAXN],mark[MAXN],dis[MAXN];//mark数组判断是否访问过,dis数组计算要变换航线的次数 
int num,n,m,a,b,c,ans;

queue<int>q;

void addedge(int a,int b,int c){
	p[num].a = a;
	p[num].b = b;
	p[num].c = c;
	p[num].next = head[a];//把起点为a的全部连起来,方便查询 
	p[num].vis = false; 
	head[a] = num++;//head数组可以记录最后一个出现起点为a的下标 
}

void dfs( int b , int c , int money ){
	if(b == n){
		ans = money;
		return;
	}
	if(!mark[b]){
		q.push(b);
		mark[b] = true;
		dis[b] = money;
	}
	for(int i = head[b] ; i != -1 ; i = p[i].next ){
		if(p[i].vis)
			continue;
		if(p[i].c == c){
			p[i].vis = true;
			dfs( p[i].b , c , money );
		}
	}
	return;
}

int bfs(){
	while(!q.empty()) 
		q.pop();
	q.push( 1 ); 
	mark[1] = 1;
	dis[1] = 0;
	while(!q.empty()){
		int tep = q.front();
		q.pop();
		for(int i = head[tep] ; i != -1 ; i = p[i].next){
			if( p[i].vis )
				continue;
			p[i].vis = true;
			dfs( p[i].b , p[i].c , dis[tep] + 1 );
			if(ans > 0)
				break;
		}
		if(ans > 0)
			break;
	}
	return ans;
}

void init(){//初始化 
	num = 0; ans = -1;
	memset(head, -1, sizeof(head));
	memset(mark, false, sizeof(mark));
	memset(dis, 0x3f3f3f3f, sizeof(dis));
}

int main(){
	while( scanf("%d%d", &n, &m) != EOF ){
		init();
		for(int i = 1; i <= m; i++){
			scanf("%d%d%d", &a, &b, &c);
			addedge( a , b , c );//双向边,所以反着也要建一条边 
			addedge( b , a , c );
		}
		printf("%d\n", bfs());
	}
}
发布了22 篇原创文章 · 获赞 19 · 访问量 3543

猜你喜欢

转载自blog.csdn.net/KnightHONG/article/details/81666048