2725: [Violet 6]故乡的梦
Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 607 Solved: 190
[ Submit][ Status][ Discuss]
Description
Input
Output
Sample Input
6 7
1 2 1
2 3 1
3 4 2
4 5 1
5 6 1
1 3 3
4 6 3
1 6
4
1 2
1 3
4 3
6 5
1 2 1
2 3 1
3 4 2
4 5 1
5 6 1
1 3 3
4 6 3
1 6
4
1 2
1 3
4 3
6 5
Sample Output
7
6
Infinity
7
6
Infinity
7
HINT
Source
先做一遍Dijkstra求出最短路,这样的路径可能很多,任取一条
删边操作如果不涉及所选择的路径,那么不会影响答案
以s为起点,再做一遍Dijkstra,求出最短路图,对于每个点,预处理
ds[i]:从s到i出发最短路长度,fs[i]:到达i的路径上,最早能在点fs[i]离开所选择的最短路
同理,以t为起点,求出dt[i]与ft[i],含义类似
这样,就能表示出所有强制经过一条边(x,y)的最优路径,即
s -> fs[x] -> x -> y -> ft[y] -> t
处理时,让fs[i]在所选最短路中尽量靠前,ft[i]在所选最短路中尽量靠后
这样,只要是删除所选路径里[fs[x],ft[y]]之间的边,总是能用路径s -> fs[x] -> x -> y -> ft[y] -> t代替
换句话说,如果不存在这样的替代品,就没办法找到s -> t最短路了
区间修改线段树完成,注意我们并不需要真的构建出最短路图,Dijkstra过程中就可以递推了
要处理的数组很多,注意下标。。一开始写炸了。。GG
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
#include<bitset>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 2E5 + 20;
const int T = 4;
typedef long long LL;
const LL INF = 1E16;
struct E{
int to; LL w; E(){}
E(int to,LL w): to(to),w(w){}
};
struct data{
int num; LL d; data(){}
data(int num,LL d): num(num),d(d){}
bool operator < (const data & b) const {return d > b.d;}
};
int n,m,q,s,t,tot,fs[maxn],ft[maxn],Num[maxn],Fa[maxn];
LL Ans,dis[maxn],ds[maxn],dt[maxn],ans[maxn],c[maxn*T];
bool vis[maxn],bo[maxn];
vector <E> v[maxn];
queue <int> Q;
priority_queue <data> Q2;
stack <int> stk;
void Dijskra()
{
for (int i = 1; i <= n; i++) dis[i] = INF,vis[i] = 0;
dis[s] = 0; Q2.push(data(s,0));
while (!Q2.empty())
{
data K = Q2.top(); Q2.pop();
int k = K.num; if (vis[k]) continue; vis[k] = 1;
for (int i = 0; i < v[k].size(); i++)
{
E e = v[k][i];
if (dis[e.to] > dis[k] + e.w)
{
dis[e.to] = dis[k] + e.w; Fa[e.to] = k;
if (!vis[e.to]) Q2.push(data(e.to,dis[e.to]));
}
}
}
Ans = dis[t]; if (Ans == INF) {while (q--) puts("Infinity"); exit(0);}
for (int z = t; z != s; z = Fa[z]) stk.push(z); stk.push(s);
while (!stk.empty())
{
int tp = stk.top(); stk.pop();
Num[tp] = ++tot; bo[tp] = 1;
}
}
void Dijskra2(int g,LL *Dis,int *fa)
{
for (int i = 1; i <= n; i++) Dis[i] = INF,vis[i] = 0;
Dis[g] = 0; Q2.push(data(g,0));
while (!Q2.empty())
{
data K = Q2.top(); Q2.pop();
int k = K.num; if (vis[k]) continue;
if (bo[k]) fa[k] = k; vis[k] = 1;
for (int i = 0; i < v[k].size(); i++)
{
E e = v[k][i];
if (Dis[e.to] > Dis[k] + e.w)
{
Dis[e.to] = Dis[k] + e.w; fa[e.to] = fa[k];
Q2.push(data(e.to,Dis[e.to]));
}
else if (Dis[e.to] == Dis[k] + e.w)
{
if (s == g && Num[fa[k]] < Num[fa[e.to]]) fa[e.to] = fa[k];
else if (t == g && Num[fa[e.to]] < Num[fa[k]]) fa[e.to] = fa[k];
}
}
}
}
void Modify(int o,int l,int r,int ml,int mr,LL g)
{
if (ml <= l && r <= mr) {c[o] = min(c[o],g); return;}
int mid = (l + r) >> 1;
if (ml <= mid) Modify(o<<1,l,mid,ml,mr,g);
if (mr > mid) Modify(o<<1|1,mid+1,r,ml,mr,g);
}
void push_all(int o,int l,int r)
{
if (l == r) {ans[l] = c[o]; return;}
int mid = (l + r) >> 1;
c[o<<1] = min(c[o<<1],c[o]);
c[o<<1|1] = min(c[o<<1|1],c[o]);
push_all(o<<1,l,mid); push_all(o<<1|1,mid+1,r);
}
int getint()
{
char ch = getchar(); int ret = 0;
while (ch < '0' || '9' < ch) ch = getchar();
while ('0' <= ch && ch <= '9')
ret = ret*10 + ch - '0',ch = getchar();
return ret;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
freopen("test.txt","w",stdout);
#else
freopen("2725.in","r",stdin);
freopen("2725.out","w",stdout);
#endif
n = getint(); m = getint();
while (m--)
{
int x = getint(),y,w;
y = getint(); w = getint();
if (x == y) continue;
v[x].push_back(E(y,w));
v[y].push_back(E(x,w));
}
s = getint(); t = getint(); q = getint();
if (s == t) {while (q--) puts("0"); return 0;}
Dijskra(); Dijskra2(s,ds,fs); Dijskra2(t,dt,ft);
for (int i = 1; i < n*T; i++) c[i] = INF;
for (int i = 1; i <= n; i++)
for (int j = 0; j < v[i].size(); j++)
{
E e = v[i][j];
int x = fs[i],y = ft[e.to];
if (!x || !y || Num[x] > Num[y] || Num[y] - Num[x] <= 1) continue;
Modify(1,1,tot,Num[x],Num[y] - 1,ds[i] + e.w + dt[e.to]);
}
push_all(1,1,tot);
while (q--)
{
int x = getint(),y = getint();
if (!bo[x] || !bo[y]) printf("%lld\n",Ans);
else
{
if (Num[x] > Num[y]) swap(x,y);
if (Num[y] - Num[x] > 1) printf("%lld\n",Ans);
else if (ans[Num[x]] == INF) puts("Infinity");
else printf("%lld\n",ans[Num[x]]);
}
}
return 0;
}