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
Input
T shows there are T test cases below. (
T≤10)
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 are
m lines. Each line has three integer
x,y,z. indicate that there is an edge frome
x to
y weighted
z.
2≤n≤100,000
0≤m≤200,000
1≤K,z≤1,000,000,000
1≤x,y≤n
Output
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;
}