题目链接
- 题意:
第一行是N,S,E,N个点,S为起点,N为重点;第二行是M,然后M行,每行代表a到b有一个值为c的边;之后是K,每行代表a到b有一个值为c的边。
对于K条边,最多只能用一条,求S到E的最短路。输出:路径+使用的特殊边的起点(即路径中第一个出现的特殊边的点号,没有的话输出“Ticket Not Used”)+最短距离 - 思路:
既然每条特殊边只能用一次,那么先考虑一下枚举每个特殊边。必须使用这条边(a->b)的距离的最小值是多少呢?必然是起点到a的最短距离加上边长加上b到终点的最短距离。分析到这里就可以发现其实对于每条边,我们都需要知道它的两个点分别到起点和终点的最短路,即起点和终点各一次dijskstra算法即可。
- 重点:
分析出起点和终点各一次dijskstra算法
考虑不需要任何特殊边的路径
每个特殊边应该有两次操作(a到起点的最短路和终点的最短路,两个情况不能少)
路径的输出
const int MAXV = 600;
const int MAXE = 1100;
//堆优化的Dijkstra
struct Edge
{
int from, to, dist;
};
struct HeapNode
{
int d, u;
bool operator < (const HeapNode& rhs) const
{
return d > rhs.d;
}
};
int ans;
vector<int> vt;
struct Dijkstra
{
int n, m;
vector<Edge> edges;
vector<int> G[MAXV];
bool done[MAXV]; // 是否已永久标号
int d[MAXV]; // s到各个点的距离
int p[MAXV]; // 最短路中的上一条弧
void init(int n)
{
this->n = n;
for(int i = 0; i < n; i++) G[i].clear();
edges.clear();
}
void AddEdge(int from, int to, int dist)
{
edges.push_back((Edge) { from, to, dist });
m = edges.size();
G[from].push_back(m - 1);
}
void dijkstra(int s)
{
priority_queue<HeapNode> Q;
for(int i = 0; i < n; i++) d[i] = INF;
d[s] = 0;
memset(done, 0, sizeof(done));
Q.push((HeapNode) { 0, s });
while(!Q.empty())
{
HeapNode x = Q.top();
Q.pop();
int u = x.u;
if(done[u]) continue;
done[u] = true;
for(int i = 0; i < G[u].size(); i++)
{
Edge& e = edges[G[u][i]];
if(d[e.to] > d[u] + e.dist)
{
d[e.to] = d[u] + e.dist;
p[e.to] = G[u][i];
Q.push((HeapNode) { d[e.to], e.to });
}
}
}
}
void display1(int u)
{
if (d[u] == 0) goto end;
display1(edges[p[u]].from);
end:;
vt.push_back(u + 1);
}
void display2(int u)
{
vt.push_back(u + 1);
if (d[u] == 0) return;
display2(edges[p[u]].from);
}
} sd, ed;
void display()
{
int len = vt.size();
REP(i, len)
{
if (i) putchar(' ');
printf("%d", vt[i]);
}
puts("");
}
int main()
{
// freopen("in.txt", "r", stdin);
int N, S, E, M, K, a, b, c, t, u, v;
int kase = 0;
while (~RIII(N, S, E))
{
if(kase != 0) printf("\n");
vt.clear();
S--; E--;
ans = INF;
sd.init(N);
ed.init(N);
RI(M);
REP(i, M)
{
RIII(a, b, c); a--; b--;
sd.AddEdge(a, b, c);
sd.AddEdge(b, a, c);
ed.AddEdge(a, b, c);
ed.AddEdge(b, a, c);
}
sd.dijkstra(S);
ed.dijkstra(E);
RI(K);
REP(i, K)
{
RIII(a, b, c); a--; b--;
if ((t = sd.d[a] + ed.d[b] + c) < ans)
{
u = a;
v = b;
ans = t;
}
else if ((t = sd.d[b] + ed.d[a] + c) < ans)
{
u = b;
v = a;
ans = t;
}
}
if (sd.d[E] < ans)
{
ans = sd.d[E];
sd.display1(E);
display();
puts("Ticket Not Used");
}
else
{
sd.display1(u);
ed.display2(v);
display();
WI(u + 1);
}
WI(ans);
kase = 1;
}
return 0;
}