UVA 11374
题目链接:
https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=2369&mosmsg=Submission+received+with+ID+16028375
题意:
给一个图n个点,起点S,终点E。
有一些正常线,每条线无向,有权值。
有一些经济线,每条线无向,有权值。
正常线随意坐,经济线至多坐一趟,问如何最快的到达终点。输出先后经过的站台、乘坐经济线的站台(没有则输出特殊语句噢~)、最短时间。
格式有要求,两个case之间有空格。
思路:
论如何以更丑的姿势过题。
看了大白书的题解打的。
首先可能有不经过经济线就能最快达到终点的方法。
其次枚举所有经济线,然后分别以它两段作为u,v。求最小的dis[s][u] + val + dis[v][e]即可(此处有坑,边为无向)(只是个示例)。
UVA各种坑啊,明明PE爆WA。
源码:
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <queue>
#include <stack>
using namespace std;
#define N 1005
#define M 2005
#define inf 1000000000
int cnt, n, m, k;
int head[N];
struct Edge
{
int u, v, val;
int ne;
Edge(){}
Edge(int _u, int _v, int _val){u = _u, v = _v, val = _val, ne = head[u];}
}edge[M * 2];
void addedge(int u, int v, int val)
{
edge[cnt] = Edge(u, v, val);
head[u] = cnt++;
}
int ds[N], de[N];
void init()
{
memset(head, -1, sizeof(head));
cnt = 0;
}
struct Dot
{
int u;
Dot(){}
Dot(int _u){u = _u;}
bool operator < (const Dot &arg)const
{
return de[u] > de[arg.u];
}
};
int pre[N], last[N];
int out[N];
int vis[N];
priority_queue<Dot>que;
stack<int>sta;
void dijkstra(int u)
{
for(int i = 1 ; i <= n ; i++)
de[i] = inf, vis[i] = 0;
de[u] = 0;
while(!que.empty()) que.pop();
que.push(Dot(u));
last[u] = u;
vis[u] = 1;
while(!que.empty())
{
int u = que.top().u; que.pop();
int now = head[u];
while(now != -1){
int v = edge[now].v;
if(de[v] > de[u] + edge[now].val){
de[v] = de[u] + edge[now].val;
last[v] = u;
if(vis[v] == 0)
que.push(Dot(v)), vis[v] = 1;
}
now = edge[now].ne;
}
}
}
int main()
{
int fii = 1;
int s, e;
while(scanf("%d%d%d", &n, &s, &e) != EOF){
if(fii) fii = 0;
else printf("\n");
init();
scanf("%d", &m);
int u, v, val;
for(int i = 0 ; i < m ; i++){
scanf("%d%d%d", &u, &v, &val);
addedge(u, v, val);
addedge(v, u, val);
}
dijkstra(s);
for(int i = 1 ; i <= n ; i++){
ds[i] = de[i], pre[i] = last[i];
// printf("de[%d] = %d\n", i, de[i]);
}
for(int i = 1 ; i <= n ; i++)
de[i] = inf;
dijkstra(e);
// for(int i = 1 ; i <= n ; i++)
// printf("de[%d] = %d, last[%d] = %d\n", i, de[i], i, last[i]);
int ok = 0;
int ans = ds[e];
int u0 = s, v0 = s;
scanf("%d", &m);
for(int i = 1 ; i <= m ; i++){
scanf("%d%d%d", &u, &v, &val);
if(ans > ds[u] + de[v] + val){
ans = ds[u] + de[v] + val;
u0 = u, v0 = v;
ok = 1;
}
if(ans > ds[v] + de[u] + val){
ans = ds[v] + de[u] + val;
u0 = v, v0 = u;
ok = 1;
}
}
int tans = u0;
while(!sta.empty()) sta.pop();
memset(vis, 0, sizeof(vis));
while(u0 != s){
if(vis[u0] == 0)
sta.push(u0), vis[u0] = 1;
u0 = pre[u0];
}
cnt = 0;
out[cnt++] = s;
vis[s] = 1;
while(!sta.empty())
out[cnt++] = sta.top(), sta.pop();
while(v0 != e){
if(vis[v0] == 0)
out[cnt++] = v0, vis[v0] = 1;
v0 = last[v0];
}
out[cnt++] = e;
int f = 1;
for(int i = 0 ; i < cnt ; i ++){
if(f) f = 0;
else printf(" ");
printf("%d", out[i]);
}
printf("\n");
if(!ok)
printf("Ticket Not Used\n");
else
printf("%d\n", tans);
printf("%d\n", ans);
}
return 0;
}
/*
4 1 4
4
1 2 2
1 3 3
2 4 4
3 4 5
0
*/