NEU 1690 (最短路+LCA)
生活随笔
收集整理的這篇文章主要介紹了
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)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 轻巧的批量图片压缩工具imgfast
- 下一篇: 2022-2028全球与中国颈挂式蓝牙耳