题意:有一张n个点的带权无向图,其中有m条经济线,k条商务线。规定经济线可以走任意次,但只能走一或零条商务线。问从s走到e的最短路。
思路:
先用dijkstra求出任意一点到起点和终点的最短路,记作dists[],diste[]。
再枚举乘坐的是那一条商务线,记作X->Y。
最后的结果就是min{dists[X]+v[x][y]+diste[y]}。
注意:
1、priority_queue是大根堆,小于运算符不能定反了。
2、商务线也是无向的,X->Y和Y->X要算两遍。
3、输出格式。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxn 500
#define maxm 1000
struct Pair {
int x,y;
Pair(int xx=0,int yy=0) {
x=xx,y=yy;
}
bool operator < (const Pair& oth) const {
return x>oth.x;
}
};
int n; //n个点
int s,e; //起点
int m,k; //边
vector<Pair> a[maxn+5]; //经济线
Pair b[maxm*2+5]; //商业线
int v[maxm*2+5];
int dists[maxn+5]; //起点到每个点的最短路
int diste[maxn+5]; //终点到每个点的最短路
vector<int> ans1,ans2;
void init() { //初始化
for(int i=1; i<=maxn; i++) a[i].clear();
ans1.clear(),ans2.clear();
}
void readin() { //读入
scanf("%d",&m);
for(int i=1; i<=m; i++) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
a[x].push_back(Pair(y,z));
a[y].push_back(Pair(x,z));
}
scanf("%d",&k);
for(int i=1; i<=k; i++) {
scanf("%d%d%d",&b[i].x,&b[i].y,&v[i]);
b[i+k].x=b[i].y,b[i+k].y=b[i].x,v[i+k]=v[i];
}
k*=2;
}
void dijkstra(int* dist,int bg) { //dijkstra
priority_queue<Pair> p;
bool c[maxn+5]= {0};
for(int i=1; i<=n; i++) dist[i]=(1<<29);
dist[bg]=0;
p.push(Pair(0,bg));
while(!p.empty()) {
Pair x=p.top();
p.pop();
if(c[x.y]) continue;
c[x.y]=true;
for(int i=0; i<a[x.y].size(); i++) {
if(dist[a[x.y][i].x]>x.x+a[x.y][i].y) {
dist[a[x.y][i].x]=x.x+a[x.y][i].y;
p.push(Pair(dist[a[x.y][i].x],a[x.y][i].x));
}
}
}
}
void find(int* dist,int x,vector<int>& ans) { //寻找路径
while(dist[x]) {
ans.push_back(x);
for(int i=0; i<a[x].size(); i++) {
if(dist[a[x][i].x]+a[x][i].y==dist[x]) {
x=a[x][i].x;
break;
}
}
}
ans.push_back(x);
}
void print() { //输出
int ans=dists[e],x,y;
for(int i=1; i<=k; i++) {
if(v[i]+dists[b[i].x]+diste[b[i].y]<ans) {
ans=v[i]+dists[b[i].x]+diste[b[i].y];
x=b[i].x,y=b[i].y;
}
}
if(ans!=dists[e]) {
find(dists,x,ans1),find(diste,y,ans2);
for(int i=ans1.size()-1; i>=0; i--) {
printf("%d ",ans1[i]);
}
printf("%d",ans2[0]);
for(int i=1; i<ans2.size(); i++) {
printf(" %d",ans2[i]);
}
printf("\n%d\n%d\n",x,ans);
} else {
find(dists,e,ans1);
printf("%d",ans1[ans1.size()-1]);
for(int i=ans1.size()-2; i>=0; i--) {
printf(" %d",ans1[i]);
}
printf("\nTicket Not Used\n%d\n",ans);
}
}
int main() {
int t=0;
while(~scanf("%d%d%d",&n,&s,&e)) {
if(t) printf("\n");
t++;
init();
readin();
dijkstra(dists,s);
dijkstra(diste,e);
print();
}
return 0;
}