第一題: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;
}