dij最短路 + 条件限制
这道题很有意思,加深了我对Dij的理解。
题意很简单,找一条从1到n的最短路,但若是前一条路和后一条路一致,那么就不计算后一条路,不然不一样了就+1,即边权全是1或0,是0是1取决于前一权值是否和当前权值一致。
那么关键点在哪里呢?
对于dij堆优化的理解。
首先,优先队列里存放的到底是什么?
是待选答案。
vis数组起到什么作用?
区分处理完的集合,和待处理数据的集合。
那么优先队列起到的是取出待处理数据中离处理完集合 距离最小的那个。
这看似是非常基础的dij最短路的知识,但在这道题中是一个关键点。
平常dij都有这段
if(!vis[v]&&dis[v] > w+dis[u]){
dis[v] = w+dis[u];
q.push(qnode{ v,dis[v]});
}
这里是用以处理好的点的最短路去不停的更新未访问结点的最短路,直到访问过的点的最短路比一个未访问点的最短路长了,那么那个点就一定是到源点的最短路径了(比它短的都更新过它了)
所以存一下边,dij就可以了
#include<iostream>
#include<stdio.h>
#include<string>
#include<cstring>
#include<vector>
#include<stack>
#include<algorithm>
#include<queue>
using namespace std;
#define clr(a, x) memset(a, x, sizeof(a))
#define mp(x, y) make_pair(x, y)
#define pb(x) push_back(x)
#define X first
#define Y second
#define fastin \
ios_base::sync_with_stdio(0); \
cin.tie(0);
typedef long long LL;
typedef pair<int, int> PII;
typedef vector<int> VI;
const int INF=0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const int N=100010;
const int M=400010;
int head[N];
int top;
int n,m;
struct Edge
{
int val;
int to;
int next;
}edge[M];
void addedge(int a,int b,int c)
{
edge[top].to=b;
edge[top].val=c;
edge[top].next=head[a];
head[a]=top++;
}
void init()
{
top=0;
clr(head,-1);
}
int dis[N];
int vis[N];
struct qnode
{
int id;
int pre;
int dis;
bool operator <(const qnode &r)const
{
return dis>r.dis;
}
};
void Dij(int start)
{
clr(vis,0);
clr(dis,INF);
priority_queue<qnode> q;
dis[start] = 0;
q.push(qnode{start,-1,0});
while(!q.empty()){
qnode cur=q.top();
q.pop();
int u=cur.id;
if(vis[u]) continue;
vis[u]=1;
for(int i=head[u];~i;i=edge[i].next){
int v=edge[i].to,w=edge[i].val;
if(!vis[v]&&dis[v]>=dis[u]+(w!=cur.pre)){
dis[v]=dis[u]+(w!=cur.pre);
q.push(qnode{v,w,(w!=cur.pre) + dis[u]});
}
}
}
}
int main() {
while(~scanf("%d%d", &n, &m)) {
init();
int u, v, w;
for(int i=1; i<=m; i++) {
scanf("%d%d%d", &u, &v, &w);
addedge(u, v, w);
addedge(v, u, w);
}
Dij(1);
if(dis[n] == INF) printf("-1\n");
else printf("%d\n", dis[n]);
}
return 0;
}
/*
6 6
1 2 2
3 6 2
1 4 3
4 6 3
3 6 2
5 6 2
*/
/*
6 6
1 2 2
3 6 2
1 4 3
4 6 3
3 6 2
5 6 2
*/