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