BZOJ 2125: 最短路
2125: 最短路
Time Limit: 1 Sec Memory Limit: 259 MBSubmit: 756 Solved: 331
[Submit][Status][Discuss]
Description
给一个N个点M条边的连通无向图,满足每条边最多属于一个环,有Q组询问,每次询问两点之间的最短路径。
Input
输入的第一行包含三个整数,分别表示N和M和Q 下接M行,每行三个整数v,u,w表示一条无向边v-u,长度为w 最后Q行,每行两个整数v,u表示一组询问
Output
输出Q行,每行一个整数表示询问的答案
Sample Input
9 10 2
1 2 1
1 4 1
3 4 1
2 3 1
3 7 1
7 8 2
7 9 2
1 5 3
1 6 4
5 6 1
1 9
5 7
1 2 1
1 4 1
3 4 1
2 3 1
3 7 1
7 8 2
7 9 2
1 5 3
1 6 4
5 6 1
1 9
5 7
Sample Output
5
6
6
HINT
对于100%的数据,N<=10000,Q<=10000
Source
1 #include <cstdio> 2 #include <cstring> 3 4 inline int nextChar(void) 5 { 6 static const int siz = 1 << 20; 7 8 static char buf[siz]; 9 static char *hd = buf + siz; 10 static char *tl = buf + siz; 11 12 if (hd == tl) 13 fread(hd = buf, 1, siz, stdin); 14 15 return int(*hd++); 16 } 17 18 inline int nextInt(void) 19 { 20 int r = 0, c = nextChar(); 21 22 for (; c < 48; c = nextChar()); 23 for (; c > 47; c = nextChar()) 24 r = r * 10 + c - '0'; 25 26 return r; 27 } 28 29 template <class T> 30 inline T min(const T &a, const T &b) 31 { 32 return a < b ? a : b; 33 } 34 35 template <class T> 36 inline T abs(const T &x) 37 { 38 return x < 0 ? -x : x; 39 } 40 41 const int mxn = 500005; 42 const int inf = 0x3f3f3f3f; 43 44 int n, m, q; 45 46 int tot; 47 int hd[mxn]; 48 int to[mxn]; 49 int vl[mxn]; 50 int nt[mxn]; 51 52 inline void add(int x, int y, int w) 53 { 54 nt[tot] = hd[x]; 55 to[tot] = y; 56 vl[tot] = w; 57 hd[x] = tot++; 58 } 59 60 int dis[mxn]; 61 int que[mxn]; 62 int vis[mxn]; 63 64 inline void spfa(void) 65 { 66 memset(vis, 0, sizeof vis); 67 memset(dis, inf, sizeof dis); 68 69 int lt = 0, rt = 0; 70 71 que[rt++] = 1; 72 vis[1] = 1; 73 dis[1] = 0; 74 75 while (lt != rt) 76 { 77 int u = que[lt++], v; 78 79 if (lt > mxn)lt = 0; 80 81 vis[u] = 0; 82 83 for (int i = hd[u]; ~i; i = nt[i]) 84 if (v = to[i], dis[v] > dis[u] + vl[i]) 85 { 86 dis[v] = dis[u] + vl[i]; 87 88 if (!vis[v]) 89 { 90 vis[que[rt++] = v] = 1; 91 92 if (rt > mxn)rt = 0; 93 } 94 } 95 } 96 } 97 98 struct data 99 { 100 int u, v, w; 101 102 inline data(void) {}; 103 inline data(int a, int b, int c) 104 : u(a), v(b), w(c) {}; 105 }stk[mxn]; int top; 106 107 int tim; 108 int dfn[mxn]; 109 int low[mxn]; 110 111 int cnt; 112 int cir[mxn]; 113 int len[mxn]; 114 int bel[mxn]; 115 int fat[mxn][25]; 116 117 inline void addcir(int u, int v) 118 { 119 ++cnt; 120 121 while (u != stk[top].u && v != stk[top].v) 122 { 123 int x = stk[top].u, y = stk[top].v, w = stk[top].w; 124 125 if (x != u)bel[x] = cnt, fat[x][0] = u; 126 if (y != u)bel[y] = cnt, fat[y][0] = u; 127 128 len[cnt] += w, cir[x] = cir[y] + w; 129 130 --top; 131 } 132 133 { 134 int x = stk[top].u, y = stk[top].v, w = stk[top].w; 135 136 len[cnt] += w, cir[x] = cir[y] + w; 137 138 fat[y][0] = x; 139 140 --top; 141 } 142 } 143 144 void tarjan(int u, int f) 145 { 146 dfn[u] = low[u] = ++tim; 147 148 for (int i = hd[u], v; ~i; i = nt[i]) 149 if ((v = to[i]) != f) 150 { 151 if (!dfn[v]) 152 { 153 stk[++top] = data(u, v, vl[i]), tarjan(v, u); 154 155 if (low[v] < low[u])low[u] = low[v]; 156 157 if (low[v] >= dfn[u])addcir(u, v); 158 } 159 else if (dfn[v] < low[u]) 160 low[u] = dfn[v], stk[++top] = data(u, v, vl[i]); 161 } 162 } 163 164 int dep[mxn]; 165 166 void build(int u) 167 { 168 for (int i = hd[u]; ~i; i = nt[i]) 169 dep[to[i]] = dep[u] + 1, build(to[i]); 170 } 171 172 inline void prework(void) 173 { 174 spfa(); 175 176 tarjan(1, 0); 177 178 for (int i = 1; i <= 20; ++i) 179 for (int j = 1; j <= n; ++j) 180 fat[j][i] = fat[fat[j][i - 1]][i - 1]; 181 182 memset(hd, -1, sizeof hd), tot = 0; 183 184 for (int i = 2; i <= n; ++i) 185 add(fat[i][0], i, 0); 186 187 dep[1] = 1, build(1); 188 } 189 190 inline int getLCA(int a, int b, int &x, int &y) 191 { 192 if (dep[a] < dep[b]) 193 a ^= b ^= a ^= b; 194 195 int ret = dis[a] + dis[b]; 196 197 for (int i = 20; ~i; --i) 198 if (dep[fat[a][i]] >= dep[b]) 199 a = fat[a][i]; 200 201 if (a == b) 202 return x = y = a, ret - dis[a] * 2; 203 204 for (int i = 20; ~i; --i) 205 if (fat[a][i] != fat[b][i]) 206 a = fat[a][i], 207 b = fat[b][i]; 208 209 return x = a, y = b, ret - dis[fat[a][0]] * 2; 210 } 211 212 signed main(void) 213 { 214 n = nextInt(); 215 m = nextInt(); 216 q = nextInt(); 217 218 memset(hd, -1, sizeof(hd)), tot = 0; 219 220 for (int i = 1; i <= m; ++i) 221 { 222 int x = nextInt(); 223 int y = nextInt(); 224 int w = nextInt(); 225 226 add(x, y, w); 227 add(y, x, w); 228 } 229 230 prework(); 231 232 for (int i = 1, x, y; i <= q; ++i) 233 { 234 int a = nextInt(); 235 int b = nextInt(); 236 237 int ans = getLCA(a, b, x, y); 238 239 if (bel[x] && bel[x] == bel[y]) 240 { 241 ans = dis[a] + dis[b] - dis[x] - dis[y]; 242 243 int len1 = abs(cir[x] - cir[y]); 244 int len2 = len[bel[x]] - len1; 245 246 ans += min(len1, len2); 247 } 248 249 printf("%d\n", ans); 250 } 251 }
@Author: YouSiki