hdu 5168(最短路----待解决)

本文介绍了一种类似于迪杰斯特拉算法的处理方法,用于在一个带权有向图中寻找从节点1到节点n的最短合法路径。合法路径定义为路径上每条边的权重至少比前一条边的权重大K。

Legal path

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 354    Accepted Submission(s): 92


Problem Description
Given a directed graph ,every edge has a weight.
A legal route is defined as the list of edge, for every edge's weight should at least K greater than last edge's weight,if the last one exist. the length of a legal route is the total weight of the edge on it.
We should find the legal path from node 1 to node n of minimum length.
 

Input
There is a number T shows there are T test cases below. (T10)
For each test case , the first line contains three integers n,m,K,n,m means the number of nodes and the number of edges on the graph. In following there arem lines. Each line has three integer x,y,z. indicate that there is an edge frome x to y weighted z.

2n100,000
0m200,000
1K,z1,000,000,000
1x,yn
 

Output
For each case ,if there is no legal path from 1 to n, output -1 ,otherwise output the answer.
 

Sample Input
3 3 2 1 1 2 1 2 3 2 3 2 1 1 2 2 2 3 1 4 6 2 1 2 1 1 2 2 2 3 3 1 3 5 2 4 2 3 4 7
 

Sample Output
3 -1 11
我的思路:类似于迪杰斯特拉算法的处理方式,dis[u]表示到达u节点的最小的legal path,pre[u]表示通过legal path到达u点时,u的入边。
这样做松弛操作时,就会要多考虑一些情况,如果dis[u] + edge > dis[v],那么pre[v]=edge,如果dis[u] + edge = dis[v],说明v之前被更新过,
找到最小的pre[v],因为这里要保证legal path最短,并且符合最优子结构,所以只需维护最小的pre即可.这里采用优先队列优化
一直WA....还没有找到哪里错了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

const int maxn = 100005;
const __int64 inf = 0x3f3f3f3f*0x3f3f3f3f;
struct Edge
{
	int to,next;
	__int64 c;
}edge[maxn<<2];
struct Node
{
	int cur;
	__int64 dis,pre;

	Node(){}
	Node(__int64 _dis,__int64 _pre,int _cur)
	{
		dis = _dis;
		pre = _pre;
		cur = _cur;
	}
	friend bool operator < (Node a,Node b)
	{
		if(a.dis != b.dis)
			return a.dis > b.dis;
		return a.pre > b.pre;
	}
};
int n,m;
int head[maxn],tot;
__int64 k,dis[maxn],pre[maxn];
bool vis[maxn];
priority_queue<Node> q;

void init()
{
	tot = 0;
	memset(head,-1,sizeof(head));
	memset(vis,false,sizeof(vis));
	for(int i = 1; i <= n; i++)
		dis[i] = pre[i] = inf;
}

void addedge(int u,int v,__int64 c)
{
	edge[tot].to = v;
	edge[tot].c = c;
	edge[tot].next = head[u];
	head[u] = tot++;
}

void Dijkstra(int src,int des)
{
	while(!q.empty()) q.pop();
	dis[src] = pre[src] = 0;
	Node now;
	q.push(Node(0,0,src));
	while(!q.empty())
	{
		now = q.top();
		q.pop();
		int u = now.cur;
		if(vis[u]) continue;
		vis[u] = true;
		for(int i = head[u]; i != -1; i = edge[i].next)
		{
			int v = edge[i].to;
			if(vis[v] || (u != src && pre[u] + k > edge[i].c)) continue;
			if(dis[v] > dis[u] + edge[i].c)
			{
				dis[v] = dis[u] + edge[i].c;
				pre[v] = edge[i].c;
				q.push(Node(dis[v],pre[v],v));
			}
			else if(dis[v] == dis[u] + edge[i].c && pre[v] > edge[i].c)
			{
				pre[v] = edge[i].c;
				q.push(Node(dis[v],pre[v],v));
			}
		}
	}
	if(dis[des] == inf)
		printf("-1\n");
	else printf("%I64d\n",dis[des]);
}

int main()
{
	int t,u,v;
	__int64 c;
	scanf("%d",&t);
	while(t--)
	{	
		scanf("%d%d%I64d",&n,&m,&k);
		init();
		for(int i = 1; i <= m; i++)
		{
			scanf("%d%d%I64d",&u,&v,&c);
			addedge(u,v,c);
			addedge(v,u,c);
		}
		Dijkstra(1,n);
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值