利用Dijikstra最短路特定寫法求次短路,DP

第一題:2019暑假牛客第4場J-free:
在這裏插入圖片描述
在這裏插入圖片描述
官方題解:
在這裏插入圖片描述
AC代碼:

#include<bits/stdc++.h>
#define per(i,a,b) for(int i = (a);i <= (b);++i)
#define rep(i,a,b) for(int i = (a);i >= (b);--i)
using namespace std;
#define INF 1e9
const int maxn = 1e5 + 10;
int n = 0,m = 0,s = 0,t = 0,k = 0;
int head[maxn],cnt = 0;
int dist[maxn];
struct node{
	int v,dis,kk;
	bool operator < (const node& c)const{
		return c.dis > this->dis;
	}
};
struct Edge{
	int to,w,nex;
}e[maxn];
void init(){
	cnt = 0;
	per(i,1,n){
		head[i] = -1; dist[i] = INF;
	}
}
void add_edge(int from,int to,int w){
	e[++cnt].to = to;
	e[cnt].w = w;
	e[cnt].nex = head[from];
	head[from] = cnt;
}
int dijikstra(){//將DP嵌入最短路中,或者說最短路就是DP,還有要使用這種寫法,才能將DP嵌入
	dist[s] = 0;//最短路還有次短路都要儲存
	priority_queue<node> pq;
	pq.push(node{s,0,0});
	while(!pq.empty()){
		node u = pq.top(); pq.pop();
		for(int i = head[u.v];i != -1;i = e[i].nex){
			int to = e[i].to;
			if(dist[u.v] + e[i].w < dist[to]){//這條邊不選爲免費邊
				dist[to] = dist[u.v] + e[i].w;
				pq.push(node{to,dist[to],u.kk});
			}
			if(u.kk < k){//可行性判斷
				if(dist[to] > u.dis){//優化判斷
					dist[to] = u.dis;//將這條邊變爲免費邊
					pq.push(node{to,dist[to],u.kk+1});
				}
			}
		}
	}
	return dist[t];
}
int main(){
	while(~scanf("%d %d %d %d %d",&n,&m,&s,&t,&k)){
		init();
		per(i,1,m){
			int a = 0,b = 0,l = 0;
			scanf("%d %d %d",&a,&b,&l);
			add_edge(a,b,l); add_edge(b,a,l);
		}
		int ans = dijikstra();
		printf("%d\n",ans);
	}

	return 0;
}

第二題:杭電多校HDU6181:
題目傳送門
AC code:

#include<bits/stdc++.h>
// #include<iostream>
// #include<cstdio>
// #include<vector>
// #include<cstring>
using namespace std;
#define per(i,a,b) for(int i = (a);i <= (b);++i)
#define rep(i,a,b) for(int i = (a);i >= (b);--i)
const int maxn = 2e5 + 10;
typedef long long LL;
#define INF 1e18
int n = 0,m = 0;
int cnt = 0,head[maxn];
LL d1[maxn],d2[maxn];
bool vis[maxn];
struct Edge{
	int to;
	LL w;
	int nex;
	bool operator < (const Edge& ed)const{
		return ed.w < this->w;//注意符號的順序
	}
	Edge(){}
	Edge(int to1,LL w1,int nex1){
		to = to1; nex = nex1; w = w1;
	}
};
Edge e[maxn];
void init(){
	cnt = 0;
	per(i,0,n){
		head[i] = -1;
		d1[i] = d2[i] = INF;
	}
}

void add_edge(int from,int to,LL w){
	e[++cnt].to = to;
	e[cnt].w = w;
	e[cnt].nex = head[from];
	head[from]  = cnt;
}

void dijikstra(int s){
	// memset(vis,false,sizeof(vis));
	d1[s] = 0;
	priority_queue<Edge> pq;
	Edge tmp;	
	tmp.to = s; tmp.w= 0;
	pq.push(tmp);
	// Edge Next;
	while(!pq.empty()){
		Edge u = pq.top();
		pq.pop();
		if(d2[u.to] < u.w){	
			continue;
		}
		for(int i = head[u.to];i != -1;i = e[i].nex){
			Edge ed = e[i];
			LL way = u.w + ed.w;//	
			if(d1[ed.to] > way){//最短路
				swap(d1[ed.to],way);
				pq.push(Edge{ed.to,d1[ed.to],ed.nex});
			}
			if(d2[ed.to] > way && d1[ed.to] < way){//記錄次短路
				d2[ed.to] = way;
				pq.push(Edge{ed.to,d2[ed.to],ed.nex});
			}
		}
	}

	printf("%lld\n",d2[n]);
}
int main(){
	int T = 0;
	scanf("%d",&T);
	while(T--){
		scanf("%d %d",&n,&m);
		init();
		per(i,1,m){
			int x = 0,y = 0;
			LL w = 0;
			scanf("%d %d %lld",&x,&y,&w);
			add_edge(x,y,w); add_edge(y,x,w);
		}
		dijikstra(1);
	}

	return 0;
}

也是A*模板題:

#include<bits/stdc++.h>
#define per(i,a,b) for(int i = (a);i <= (b);++i)
#define rep(i,a,b) for(int i = (a);i >= (b);--i)
#define INF 1e18
using namespace std;
typedef long long LL;
const int maxn = 1e5 + 10;
int n = 0,m = 0;
LL d[maxn];
int head[maxn];
int cnt = 0;
bool vis[maxn];
struct node{
	int v;
	LL c;
	bool operator < (const node& x)const{
		return x.c + d[x.v] < this->c + d[this->v];
	}

};
struct Edge{
	int to,nex;
	LL w;
}e[2*maxn];//需要兩倍的空間,每一次是有向邊
void init(){
	cnt = 0;
	per(i,1,n){
		head[i] = -1;
		d[i] = INF;
		vis[i] = false;
	}
}
void add_edge(int from,int to,LL w){//鏈式前向星
	e[++cnt].to = to;
	e[cnt].w = w;
	e[cnt].nex = head[from];
	head[from] = cnt;
}

void dijikstra(int s){//求出每個點到終點的距離用於計算期望函數的大小
	//不需要記錄非最短的路徑長度,所以pq會根據是否訪問來排序,未訪問的爲INF
	//且沒有入棧,所以可實現優先選擇最優的點
	priority_queue<node> pq;
	d[s] = 0;
	pq.push(node{s,0});
	while(!pq.empty()){
		node u = pq.top();
		pq.pop();
		if(vis[u.v]){
			continue;	
		}
		vis[u.v] = true;
		for(int i = head[u.v];i != -1;i = e[i].nex){
			Edge ed = e[i];
			if(d[ed.to] > d[u.v] + ed.w){
				d[ed.to] = d[u.v] + ed.w;
				pq.push(node{ed.to,0});
			}
		}
	}
}

LL A_start(int s,int k){
	--k;
	priority_queue<node> pq;
	pq.push(node{s,0});
	while(!pq.empty()){
		node u = pq.top();
		pq.pop();
		if(u.v == n){
			if(k > 0){
				--k;
			}else{
				return u.c;
			}
		}
		for(int i = head[u.v];i != -1;i = e[i].nex){
			Edge ed = e[i];
			pq.push(node{ed.to,ed.w + u.c});
			//記錄從原點到該點的距離,比較時使用的是期望函數大小,還要+d[ed.to]
		}
	}
	return -1;
}
int main(){
	int T = 0;
	scanf("%d",&T);
	while(T--){
		scanf("%d %d",&n,&m);
		init();
		per(i,1,m){
			int x = 0,y = 0;
			LL w = 0;
			scanf("%d %d %lld",&x,&y,&w);
			add_edge(x,y,w); add_edge(y,x,w);
		}
		dijikstra(n);
		// per(i,1,n){
		// 	printf("%lld ",d[i]);
		// }
		// puts("");
		printf("%lld\n",A_start(1,2));
	}	

	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章