• CF 1051 F. The Shortest Statement


    F. The Shortest Statement

    http://codeforces.com/contest/1051/problem/F

    题意:

      n个点,m条边的无向图,每次询问两点之间的最短路。(m-n<=20)

    分析:

      dijkstra。

      如果是一棵树,那么可以直接通过,dis[u]+dis[v]-dis[lca]*2来求。现在如果建出一棵树,那么非树边只有小于等于21条。

      只经过树边的路径用上面的方式求出,考虑经过非树边的路径。

      经过非树边(至少一条),那么一定经过了这条边的顶点,所以可以对顶点做一次最短路,如果询问u,v经过这个顶点,那么就是dis[u]+dis[v]。

    代码:

      1 #include<cstdio>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<iostream>
      6 #include<cctype>
      7 #include<set>
      8 #include<vector>
      9 #include<queue>
     10 #include<map>
     11 #define fi(s) freopen(s,"r",stdin);
     12 #define fo(s) freopen(s,"w",stdout);
     13 using namespace std;
     14 typedef long long LL;
     15 
     16 inline int read() {
     17     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
     18     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
     19 }
     20 
     21 const LL INF = 1e18;
     22 const int N = 100005;
     23 
     24 int head[N], nxt[N << 1], to[N << 1], len[N << 1], En;
     25 int f[N][21], deth[N], tmp[100], tot;
     26 LL dis[N], d[50][N];
     27 int n, m;
     28 bool vis[N];
     29 
     30 void add_edge(int u,int v,int w) {
     31     ++En, to[En] = v, len[En] = w, nxt[En] = head[u], head[u] = En;
     32     ++En, to[En] = u, len[En] = w, nxt[En] = head[v], head[v] = En;
     33 }
     34 
     35 #define pa pair<LL,int>
     36 #define mp(a,b) make_pair(a,b)
     37 priority_queue< pa, vector< pa >, greater< pa > > q;
     38 
     39 void Dijkstra(int id,int S) {
     40     for (int i=1; i<=n; ++i) dis[i] = INF, vis[i] = false;
     41     dis[S] = 0;
     42     q.push(mp(0, S));
     43     while (!q.empty()) {
     44         int u = q.top().second; q.pop();
     45         if (vis[u]) continue;
     46         vis[u] = true;
     47         for (int i=head[u]; i; i=nxt[i]) {
     48             int v = to[i];
     49             if (dis[v] > dis[u] + len[i]) {
     50                 dis[v] = dis[u] + len[i];
     51                 q.push(mp(dis[v], v));
     52             }
     53         }
     54     }
     55     for (int i=1; i<=n; ++i) d[id][i] = dis[i];
     56 }
     57 void dfs(int u,int fa) {
     58     vis[u] = true;
     59     f[u][0] = fa;
     60     deth[u] = deth[fa] + 1;
     61     for (int i=head[u]; i; i=nxt[i]) {
     62         int v = to[i];
     63         if (v == fa) continue;
     64         if (vis[v]) tmp[++tot] = u, tmp[++tot] = v;
     65         else dis[v] = dis[u] + len[i], dfs(v, u);        
     66     }
     67 }
     68 int LCA(int u,int v) {
     69     if (deth[u] < deth[v]) swap(u, v);
     70     int d = deth[u] - deth[v];
     71     for (int i=20; i>=0; --i) 
     72         if (d & (1 << i)) u = f[u][i];
     73     if (u == v) return u;
     74     for (int i=20; i>=0; --i) 
     75         if (f[u][i] != f[v][i]) 
     76             u = f[u][i], v = f[v][i];
     77     return f[u][0];
     78 }
     79 int main() {    
     80     n = read(), m = read();
     81     for (int i=1; i<=m; ++i) {
     82         int u = read(), v = read(), w = read();
     83         add_edge(u, v, w);
     84     }
     85     
     86     dfs(1, 0);
     87     for (int i=1; i<=n; ++i) d[0][i] = dis[i];
     88     for (int j=1; j<=20; ++j) 
     89         for (int i=1; i<=n; ++i) f[i][j] = f[f[i][j-1]][j-1];
     90     sort(tmp + 1, tmp + tot + 1);
     91     int lim = tot; tot = 1;
     92     for (int i=2; i<=lim; ++i) if (tmp[tot] != tmp[i]) tmp[++tot] = tmp[i];    
     93     for (int i=1; i<=tot; ++i) Dijkstra(i, tmp[i]);
     94     
     95     int Q = read();
     96     while (Q --) {
     97         int u = read(), v = read();
     98         int t = LCA(u, v);
     99         LL ans = d[0][u] + d[0][v] - 2 * d[0][t];
    100         for (int i=1; i<=tot; ++i) 
    101             ans = min(ans, d[i][u] + d[i][v]);
    102         printf("%I64d
    ",ans);
    103     }
    104     return 0;
    105 }
  • 相关阅读:
    题解——栈(卡特兰递归数的应用)
    题解——主的赦免(递归的进一步理解)
    sql开窗函数 row_number () over(order by id )
    c# resources
    Fillder 转载
    用javascript实现控制打开网页窗口的大小 和HTML如何关闭窗口的技巧大全
    datatable 与dataview的区别
    Asp.net中DataBinder.Eval用法的总结
    FrameSet左右收缩编码
    ajax get post
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9700260.html
Copyright © 2020-2023  润新知