POJ 3767 I Wanna Go Home

略水。。

题目大意是 有n个城市,要从 第1个城市 走到 第2个城市的最短路。。(起点是1, 终点是2),但是,每个城市都属于不同的领主。。

"For the sake of safety,", said Mr.M, "your route should contain at most 1 road which connects two cities of different camp.

要求你走的最短路中, 最多包含1条连接两个城市但却属于不同的领主的路。。

dijkstra算法,+多一个sum[]数组记录 有多少条连接两个城市但却属于不同的领主的路。。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
#define eps 1e-8
#define mod 1000000007
#define mnx 20005
#define ll long long 
#define ull unsigned long long
#define inf 0x3f3f3f3f
int cost[mnx], first[mnx], vv[mnx], nxt[mnx], dis[mnx], lead[mnx], sum[mnx], e, m, n;
bool vis[mnx];
struct edge{
	int u, d;
	bool operator < (const edge &b) const {
		return d > b.d;
	}
};
void init(){
	memset(dis, 0x3f, sizeof(dis));
	memset(vis, 0, sizeof(vis));
	memset(first, -1, sizeof(first));
	memset(sum, 0, sizeof(sum));
	e = 0;
}
void add( int u, int v, int c ){
	cost[e] = c;
	vv[e] = v;
	nxt[e] = first[u];
	first[u] = e++;
}
void dijkstra(int s){
	priority_queue<edge> que;
	dis[s] = 0;
	edge q1; q1.u = s; q1.d = 0;
	que.push(q1);
	while( !que.empty() ){
		q1 = que.top(); que.pop();
		int u = q1.u;
		if( vis[u] ) continue;
		vis[u] = 1;
		for( int i = first[u]; i != -1; i = nxt[i] ){
			int v = vv[i];
			if( dis[v] > dis[u] + cost[i] ){
				if(lead[u] == lead[v] || (lead[u] != lead[v] && sum[u] + 1 < 2) ) {  //注意条件。。 
				    if( lead[u] != lead[v] ) sum[v] = sum[u] + 1;
				    else sum[v] = sum[u];
				    dis[v] = dis[u] + cost[i];
				    edge q2;
				    q2.d = dis[v], q2.u = v;
				    que.push(q2);
				}
			}
		}
	}
}
int main(){
	while( scanf("%d", &n) && n ){
		init();
		scanf("%d", &m);
		int u, v, d;
		for( int i = 0; i < m; i++ ){
			scanf("%d%d%d", &u, &v, &d);
			add(u, v, d);
			add(v, u, d);
		}
		for( int i = 1; i <= n; i++ ){
			scanf("%d", &lead[i]);
		}
		dijkstra(1);
		if( dis[2] >= inf ) printf("-1\n");
		else printf("%d\n", dis[2]);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值