標籤:des style blog http java color os 資料
Connections between cities
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4425 Accepted Submission(s): 1263
Problem Description
After World War X, a lot of cities have been seriously damaged, and we need to rebuild those cities. However, some materials needed can only be produced in certain places. So we need to transport these materials from city to city. For most of roads had been totally destroyed during the war, there might be no path between two cities, no circle exists as well.
Now, your task comes. After giving you the condition of the roads, we want to know if there exists a path between any two cities. If the answer is yes, output the shortest path between them.
Input
Input consists of multiple problem instances.For each instance, first line contains three integers n, m and c, 2<=n<=10000, 0<=m<10000, 1<=c<=1000000. n represents the number of cities numbered from 1 to n. Following m lines, each line has three integers i, j and k, represent a road between city i and city j, with length k. Last c lines, two integers i, j each line, indicates a query of city i and city j.
Output
For each problem instance, one line for each query. If no path between two cities, output “Not connected”, otherwise output the length of the shortest path between them.
Sample Input
5 3 21 3 22 4 35 2 31 44 5
Sample Output
Not connected6
題意:給你n給點,m條邊,有c次詢問,每次詢問u,v兩個點,你需要判斷u,v是否連通,u,v的最短距離是多少。
::對於是否連通直接用並查集就可以了,對於連通的兩個點最短距離怎麼求呢。
資料很大,不允許每次詢問都跑一次最短路的演算法,那麼就考慮一下一勞永逸的辦法,有沒有辦法經過預先處理,每次詢問都能快速給出答案。
注意到這是無歡圖,那沒就轉化成樹的做法。
對於單個連通分量隨意取一點,令其為根,進行dfs遍曆,得到每個點到根結點的距離,儲存起來(我這裡用dp儲存),並且得到一個dfs遍曆的尋列,求出每兩個點的lca。如何求lca具體看
lca –> rmq. 那麼對於詢問在同一個連通分量的兩個的距離dis(u,v) = dp(u)+dp(v)-2*dp(lca(u,v));//u到根結點的距離+v到根結點的距離-(u,v)最早公用祖先到根結點的距離的2倍
view code#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 10010;int n, m, c, fa[N], pre[N], id[N], now, dp[N];int E[N<<1], pos, R[N], d[N<<1][15];bool vis[N];struct edge{ int u, v, w, p; edge() {} edge(int u, int v,int w, int p):u(u), v(v), w(w), p(p) {}}e[N<<1];int ecnt;int find(int x){ return x==fa[x]?x:(fa[x]=find(fa[x]));}void init_RMQ(){ for(int i=0; i<pos; i++) d[i][0] = E[i]; for(int j=1; (1<<j)<pos; j++) for(int i=0; i+(1<<j)-1<pos; i++) d[i][j] = min(d[i][j-1], d[i+(1<<(j-1))][j-1]);}int RMQ(int L, int R){ int k=0; while((1<<(k+1)) <= R-L+1) k++; return min(d[L][k], d[R-(1<<k)+1][k]);}void dfs(int u, int h){ vis[u] = 1; id[u] = now++;//給每個結點一個新的id,為什麼要給新的id,為什麼不用原來的序號,弄懂求lca就懂了 R[id[u]] = pos; E[pos++] = id[u]; dp[id[u]] = h;//結點id[u]到根結點的距離為h for(int i=pre[u]; ~i; i=e[i].p) { int v = e[i].v; if(vis[v]) continue; dfs(v, h+e[i].w); E[pos++] = id[u]; }}void init(){ memset(vis, 0, sizeof(vis)); now = 1; pos = 0; for(int i=1; i<=n; i++) if(!vis[i]) dfs(i, 0);// for(int i=1; i<=n; i++) printf("is[%d] = %d, R=%d\n", i, id[i], R[id[i]]);// for(int i=0; i<pos; i++) printf("pos[%d] = %d\n", i, E[i]); init_RMQ();}void solve(){ for(int i=1; i<=n; i++) fa[i] = i, pre[i] = -1; ecnt = 0; int u, v, w; for(int i=0; i<m; i++) { scanf("%d%d%d", &u, &v, &w); e[ecnt] = edge(u, v, w, pre[u]); pre[u] = ecnt++; e[ecnt] = edge(v, u, w, pre[v]); pre[v] = ecnt++; u =find(u), v =find(v); fa[u] = v; } init(); while(c--) { scanf("%d%d", &u, &v); if(find(u)!=find(v)){ puts("Not connected"); continue; } u = id[u], v = id[v]; int lca = RMQ(min(R[u], R[v]), max(R[u],R[v])); int ans = dp[u]+dp[v]-2*dp[lca]; printf("%d\n", ans); }}int main(){// freopen("in.txt","r",stdin); while(scanf("%d%d%d", &n, &m, &c)>0) solve(); return 0;}