日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

NEU 1690 (最短路+LCA)

發布時間:2023/12/8 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 NEU 1690 (最短路+LCA) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1690: Terrorists

時間限制:?5 Sec??內存限制:?128 MB
提交:?11??解決:?3
[提交][狀態][討論版]

題目描述

Terrorists! There are terrorists everywhere!!! I was shouting out loud after I had watched a few news reports about terrorism acts that had happened around my neighborhoods. I started to think that hiding at home wasn’t a good way to go. I went to police stations and asked around if I could help them prevent these issues. The police gave me pieces of information about terrorists’ plans. I ended up lying on my bed and figuring way to utilize this information. That is why I come to you. Our neighborhoods could be illustrated with intersections and roads. Terrorists usually meet up at one intersection before moving to another intersection to perform an illegal act. The given information tells us where they will meet and where they will go. Unfortunately, the certain schedules of those plans are not available and too few policemen are available lately. So, the police will not be able to set up efficient defenses to all of those acts. What they could do is set up surveillance cameras to all meet up intersections. Once a meet up is detected, policemen will go to that meet up’s destination to catch the terrorists. The policemen rarely accomplish it because they spend too long time travelling between places. Because terrorists are smart, they always use shortest route to travel between intersections. Because the policemen aren’t that smart, they need our help. For each terrorist plan, the police want us to compute the shortest distance between the meet up place and the destination. If the distance is too short, they will not spend their efforts for free.

輸入

The first line of the input contains an integer T, the number of test sets (1 <= T <= 5). Each test case consists of many lines. The first line contains 3 integers N, M, Q which are the number of intersections, the number of roads, and the number of terrorists’ plans in respective order. 1 <= N <= 100 000, N - 1 <= M <= N + 50, 1 <= Q <= 50 000 Then the next M lines describe the roads in our neighborhoods. A road is described by 3 integers: U, V, D. Ui and Vi represent 2 ends of the road i. Di represents distance of that road. 1 <= Ui, Vi <= N, 1 <= Di <= 10 000. It is possible that many roads might exist between a pair of intersection. Finally the next Q lines are the terrorism plans. A plan j is described by 2 integers: Sj and Ej which are the meet-up intersection and the destination intersection respectively. 1 <= Sj, Ej <= N.

輸出

For each test set, print out “Case x:” where x is a case number beginning with 1, and then followed by Q lines. For each terrorism plan, output the shortest distance between the meet-up intersection and the destination of the plan.

樣例輸入

1 7 9 5 7 6 6114 5 3 5473 2 4 2601 5 4 8525 7 3 291 2 7 3363 1 6 399 6 4 4477 1 7 3075 6 3 4 4 3 1 2 3 7 3

樣例輸出

Case 1: 3765 0 3366 3654 291

題意:給出一幅圖,和q個詢問,每次輸出兩點之間的最短路

觀察給出的數據發現邊最多比n多50,暗示著可以通過某種暴力的手段. 先建一棵生成樹,最多有50條左右非樹邊然后對于樹上的點可以LCA搞定最近距離,對于剩下樹邊上的的每個點都跑一次SPFA,然后每次詢問取LCA和非樹邊點到詢問點距離和的最小值.這樣單組詢問的復雜度只有O(100+lgn). #include <bits/stdc++.h> using namespace std; #define maxn 111111 #define maxm 211111 #define INF 1111111111const int DEG = 20; struct Edge {int to,next, w; }edge[maxn*2]; int head[maxn],tot; int n, m, q, root; void add_edge(int u,int v, int w) {//cout << u << " " << v << endl;edge[tot].to = v;edge[tot].w = w;edge[tot].next = head[u];head[u] = tot++; } void init() {tot = 0;memset(head,-1,sizeof(head)); } int fa[maxn][DEG];//fa[i][j]表示結點i的第2^j個祖先 int deg[maxn];//深度數組 void BFS(int root) {queue<int>que;deg[root] = 0;fa[root][0] = root;que.push(root);while(!que.empty()){int tmp = que.front();que.pop();for(int i = 1;i < DEG;i++)fa[tmp][i] = fa[fa[tmp][i-1]][i-1];for(int i = head[tmp]; i != -1;i = edge[i].next){int v = edge[i].to;if(v == fa[tmp][0])continue;deg[v] = deg[tmp] + 1;fa[v][0] = tmp;que.push(v);}} } int LCA(int u,int v) {if(deg[u] > deg[v])swap(u,v);int hu = deg[u], hv = deg[v];int tu = u, tv = v;for(int det = hv-hu, i = 0; det ;det>>=1, i++)if(det&1)tv = fa[tv][i];if(tu == tv)return tu;for(int i = DEG-1; i >= 0; i--){if(fa[tu][i] == fa[tv][i])continue;tu = fa[tu][i];tv = fa[tv][i];}return fa[tu][0]; } bool flag[maxn]; int e[maxm][2], w[maxn]; bool is_edge[maxm];int p[maxn]; #define find Find int find (int x) {return p[x] == x ? p[x] : p[x] = find (p[x]); }int d[maxn]; bool vis[maxn]; int dfs (int u, int deep) {//獲取每個節點到根的距離d[u] = deep;vis[u] = 1;for (int i = head[u]; i != -1; i = edge[i].next) {int v = edge[i].to;if (vis[v])continue;dfs (v, deep+edge[i].w);} }void build () {//建一顆生成樹init ();memset (is_edge, 0, sizeof is_edge);for (int i = 1; i <= n; i++)p[i] = i;root = 1;for (int i = 1; i <= m; i++) {int u = e[i][0], v = e[i][1];int p1 = find (u), p2 = find (v);if (p1 != p2) {p[p1] = p2;is_edge[i] = 1;//加入樹邊add_edge (u, v, w[i]);add_edge (v, u, w[i]);}}BFS (root);memset (vis, 0, sizeof vis);dfs (root, 0);return ; }struct Edge2 {int v;int cost;Edge2(int _v=0,int _cost=0):v(_v),cost(_cost){} }; vector<Edge2>E[maxn]; int dis[111][maxn]; void addedge(int u,int v,int w) {E[u].push_back(Edge2(v,w)); } int cnt[maxn];//每個點的入隊列次數 bool SPFA(int start,int n,int *dist) {memset(vis,false,sizeof(vis));for(int i=1;i<=n;i++) dist[i]=INF;vis[start]=true;dist[start]=0;queue<int>que;while(!que.empty())que.pop();que.push(start);memset(cnt,0,sizeof(cnt));cnt[start]=1;while(!que.empty()){int u=que.front();que.pop();vis[u]=false;for(int i=0;i<E[u].size();i++){int v=E[u][i].v;if(dist[v]>dist[u]+E[u][i].cost){dist[v]=dist[u]+E[u][i].cost;if(!vis[v]){vis[v]=true;que.push(v);if(++cnt[v]>n)return false;}}}}return true; }int main() {//freopen ("in.txt", "r", stdin);int t, kase = 0;scanf ("%d", &t);while (t--) {scanf ("%d%d%d", &n, &m, &q);printf ("Case %d:\n", ++kase);for (int i = 1; i <= n; i++) E[i].clear ();for (int i = 1; i <= m; i++) {scanf ("%d%d%d", &e[i][0], &e[i][1], &w[i]);addedge (e[i][0], e[i][1], w[i]);addedge (e[i][1], e[i][0], w[i]);}build ();int node[maxn], node_cnt = 0;//非樹邊的點for (int i = 1; i <= m; i++) if (!is_edge[i]) {//枚舉非樹邊//cout << e[i][0] << "..." << e[i][1] << endl;node[node_cnt++] = e[i][0], node[node_cnt++] = e[i][1];}sort (node, node+node_cnt);node_cnt = unique (node, node+node_cnt)-node;for (int i = 0; i < node_cnt; i++) {//找到每個非樹邊點到其他點的最短路SPFA (node[i], n, dis[i]);/*cout << node[i] << endl;for (int j = 1; j <= n; j++) {cout << "j: " << dis[i][j] << endl;}*/}while (q--) {int u, v;scanf ("%d%d", &u, &v);long long d1 = dis[0][u]+dis[0][v];for (int i = 1; i < node_cnt; i++)d1 = min (d1, (long long)dis[i][u]+dis[i][v]);d1 = min (d1, d[u]+d[v]-(long long)2*d[LCA (u, v)]);printf ("%lld\n", d1);}}return 0; }

總結

以上是生活随笔為你收集整理的NEU 1690 (最短路+LCA)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。