【经典模板】:PID341 / 星门跳跃
题目大意:从1到N有M条边,每条边距离z,求最短路
思路:dijkstra+priority_queue。本道题由于数据非常大,时间要求严,不能全部往队列里丢数据,可以在之前加个判断,本次距离是否减小,减小则往队里扔。此外由于优先队列每次都是选取最小距离,则此距离固定,则代表已访问,标记点下次访问到此点直接跳过。
注意:
1、加判断if(visit[u])和if(D[v]==-1 || D[v]>D[u]+cost);
#include<cstdio>
#include<queue>
#include<vector>
#include<string.h>
#define MAX 300001
using namespace std;
struct node
{
int v,c;//u->v cost=c;
node (){}
node(int x,int y){v=x;c=y;}
bool operator < (const node &A) const
{
if (c==A.c)
return v>A.v;
else return c>A.c;
}
};
vector<node>g[MAX];
bool visit[MAX];
int D[MAX];
int n,m;
void Dijkstra()
{
priority_queue<node>Q;
int i,u,v,cost;
node p;
memset(visit,0,sizeof(visit));
memset(D,-1,sizeof(D));
D[1]=0;
Q.push(node(1,D[1]));
while(!Q.empty())
{
p=Q.top();Q.pop();
u=p.v;
if (visit[u])
continue;
visit[u]=true;
D[u]=p.c;
if (u==n)
break;
for (i=0;i<g[u].size();i++)
{
v=g[u][i].v;
cost=g[u][i].c;
if (D[v]==-1 || D[v]>D[u]+cost);
Q.push(node(v,D[u]+cost));
}
}
}
int main()
{
int x,y,z,i;
scanf_s("%d%d",&n,&m);
for (i=1;i<=m;i++)
{
scanf_s("%d%d%d",&x,&y,&z);
g[x].push_back(node(y,z));
g[y].push_back(node(x,z));
}
Dijkstra();
printf("%d",D[n]);
return 0;
}
变形:726:ROADS——路径有两个属性时的处理
题目大意:从1到N有m条边,每一条边有原点s,目的d,距离l和花费t,寻找从1到n的最短路,满足花费小于k
思路:dijkstra+priority_queue。由于从队列头取出的点不一定选取成功(即虽然路程最小但是花费>k),所以不能加visit和D数组的距离判断,只能把可能的路径放入队列,让优先队列自己判断
注意:
1、优先队列是按从大到小排序的!所以排序时要注意把<变成>
2、直接入队,不需要判断!!
#include<iostream>
#include<queue>
#include<vector>
#include<string.h>
#define MAX 102
using namespace std;
int n,k;
struct node
{
int v,L,t;
node(){}
node(int a,int b,int c){v=a;L=b;t=c;}
bool operator < (const node &A)const//优先队列是按从大到小排序的!!!
{
if (L==A.L && t==A.t)
return v>A.v;//要为大于号!!!
else if (L==A.L)
return t>A.t;
else return L>A.L;
}
};
vector<node> g[MAX];
int L[MAX],T[MAX];
bool flag=false;
void Dijkstra(int c)
{
priority_queue<node> Q;
node p;
int u,l,t,i,v;
memset(L,-1,sizeof(L));
memset(T,-1,sizeof(T));
L[c]=0;T[c]=0;
Q.push(node(c,L[c],T[c]));
while(!Q.empty())
{
p=Q.top();Q.pop();
u=p.v;L[u]=p.L;T[u]=p.t;
if (p.t>k)//忽略钱多的
continue;
if (u==n)
{
flag=1;return;
}
for (i=0;i<g[u].size();i++)
{
v=g[u][i].v;
t=g[u][i].t;
l=g[u][i].L;
Q.push(node(v,L[u]+l,T[u]+t));
}
}
}
int main()
{
int i,s,d,l,t,m;
cin>>k>>n>>m;
for (i=1;i<=m;i++)
{
cin>>s>>d>>l>>t;
g[s].push_back(node(d,l,t));
}
Dijkstra(1);
if(flag)
cout<<L[n];
else cout<<-1;
return 0;
}