hdu 2874
阿新 • • 發佈:2018-12-13
這道題題意很簡單
給你一個森林,輸入連通的點,最後給你多次詢問,每次問輸出兩個點 s 和 t 之間的 距離
如果沒連通就輸出 Not contence....(總之是串英文)
有些丟人。。。不會寫離線演算法。。寫了個線上演算法。。。跑了 1700ms 。。。
還是很好搞的。。因為是森林。跑最短路會出事的。所以先用並查集建立集合關係。
輸入s t 判斷一下,之後正常的求出 dis[s] + dis[t] - 2 * dis[lca]
以下是 AC 程式碼。。。
#include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int maxn = 1e5+5; const int ins = 20; int f[maxn][ins]; int pre[maxn]; int dis[maxn]; int dep[maxn]; struct node { int to,nex,val; }ed[maxn<<1]; int head[maxn],tot; int n,m,q; void add(int u,int v,int w) { ed[++tot].to = v; ed[tot].val = w; ed[tot].nex = head[u]; head[u] = tot; } void init() { tot = 0; for(int i = 0; i <= n; i++) pre[i] = i; memset(head , -1, sizeof(head)); memset(f, 0, sizeof(f)); memset(dis, 0, sizeof(dis)); memset(dep, 0, sizeof(dep)); } int findd(int x) { return x == pre[x] ? x : pre[x] = findd(pre[x]); } void merage(int a,int b) { int aa = findd(a), bb = findd(b); if(aa != bb) pre[aa] = bb; } void dfs(int x,int p,int d) { f[x][0] = p; dep[x] = dep[p] + 1; dis[x] = d; for(int i=1;i<=19;i++) { f[x][i] = f[f[x][i - 1]][i - 1]; } for(int i=head[x];~i;i=ed[i].nex) { int v = ed[i].to; if(v != p) { dfs(v, x, dis[x] + ed[i].val); } } } int lca(int a,int b) { if(dep[a] > dep[b]) swap(a,b); for(int i=19;i>=0;i--) { if(dep[f[b][i]] >= dep[a]) b = f[b][i]; } if(a == b) return a; for(int i=19;i>=0;i--) { if(f[a][i] != f[b][i]) { a = f[a][i]; b = f[b][i]; } } return f[a][0]; } int main() { while(scanf("%d%d%d",&n,&m,&q) == 3) { int u,v,w; init(); for(int i=0;i<m;i++) { scanf("%d%d%d",&u,&v,&w); add(u,v,w); add(v,u,w); merage(u,v); } for(int i=1;i<=n;i++) { if(pre[i] == i) dfs(i, 0, 0); } while(q--) { scanf("%d%d",&u,&v); if(findd(u) == findd(v)) printf("%d\n",dis[u] + dis[v] - 2 * dis[lca(u, v)]); else printf("Not connected\n"); } } return 0; }