题意:
给出n个点m条边的图,c次询问 求询问中两个点间的最短距离。
解析:
Floyd会T,所以用到了最短路树。。具体思想为:
设k为u和v的最近公共祖先 d[i] 为祖结点到i的最短距离 则dis[u][v] = d[u] + d[v] - 2*d[k]
用tarjan的lca求即可
把这题代码当作模板就好啦
#include <iostream> #include <cstdio> #include <sstream> #include <cstring> #include <map> #include <set> #include <vector> #include <stack> #include <queue> #include <algorithm> #include <cmath> #define rap(i, a, n) for(int i=a; i<=n; i++) #define MOD 2018 #define LL long long #define ULL unsigned long long #define Pair pair<int, int> #define mem(a, b) memset(a, b, sizeof(a)) #define _ ios_base::sync_with_stdio(0),cin.tie(0) //freopen("1.txt", "r", stdin); using namespace std; const int maxn = 10010, INF = 0x7fffffff; const int maxm = 1e6 + 10; int n, m, cnt1, cnt2, c; int head1[maxn], head2[maxn], f[maxn], d[maxn], vis[maxn]; int res[maxm]; struct node { int v, w, next; }Node[maxn*2]; struct edge { int v, id, next; }Edge[maxm*2]; void add1_(int u, int v, int w) { Node[cnt1].v = v; Node[cnt1].w = w; Node[cnt1].next = head1[u]; head1[u] = cnt1++; } void add1(int u, int v, int w) { add1_(u, v, w); add1_(v, u, w); } void add2_(int u, int v, int id) { Edge[cnt2].v = v; Edge[cnt2].id = id; Edge[cnt2].next = head2[u]; head2[u] = cnt2++; } void add2(int u, int v, int id) { add2_(u, v, id); add2_(v, u, id); } int find(int x) { return f[x]==x?x:(f[x] = find(f[x])); } int lca(int u, int deep, int root) { f[u] = u; d[u] = deep; vis[u] = root; // 标记属于的树 for(int i=head1[u]; i!=-1; i=Node[i].next) { node e = Node[i]; if(vis[e.v] == -1) { lca(e.v, deep+e.w, root); f[e.v] = u; } } for(int i=head2[u]; i!=-1; i=Edge[i].next) { edge e = Edge[i]; if(vis[e.v] == root) //判断另一个结点是不是和u属于一个树 { int k = find(e.v); //寻找最近公共祖先 res[e.id] = d[u] + d[e.v] - 2*d[k]; } } } void init() { mem(head1, -1); mem(head2, -1); mem(res, -1); mem(vis, -1); cnt1 = cnt2 = 0; } int main() { while(scanf("%d%d%d", &n, &m, &c) != EOF) { init(); rap(i, 1, m) { int u, v, w; scanf("%d%d%d", &u, &v, &w); add1(u, v, w); } rap(i, 1, c) { int u, v; scanf("%d%d", &u, &v); add2(u, v, i); } rap(i, 1, n) if(vis[i] == -1) lca(i, 0, i); rap(i, 1, c) { if(res[i] == -1) printf("Not connected\n"); else printf("%d\n", res[i]); } } return 0; }