zoukankan      html  css  js  c++  java
  • P2934 [USACO09JAN]安全出行Safe Travel

    P2934 [USACO09JAN]安全出行Safe Travel

    https://www.luogu.org/problemnew/show/P2934

    分析:

      建出最短路树,然后考虑一条非树边u,v,w,它可以让u->lca的路径上的点x的答案更新为dis[v]+dis[u]+w-dis[x]。为从1走到v(dis[v]),从v走到u(+w),从u走到x,(dis[u]-dis[x])。

      然后对于每条非树边,按照dis[v]+dis[u]+w排序,然后会发现每个点只会更新一次,然后用并查集维护。

    代码:

      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 using namespace std;
     12 typedef long long LL;
     13 
     14 inline int read() {
     15     int x=0,f=1;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1;
     16     for(;isdigit(ch);ch=getchar())x=x*10+ch-'0';return x*f;
     17 }
     18 
     19 const int N = 400100;
     20 const int INF = 1e9;
     21 
     22 struct Edge{
     23     int u,v,w,lca;
     24     Edge() {}
     25     Edge(int a,int b,int c,int d) { u = a, v = b, w = c; lca = d;}
     26     bool operator < (const Edge &A) const {
     27         return w < A.w;
     28     }
     29 }e[N];
     30 int fa[N], far[N], ans[N], n;
     31 
     32 namespace ShortestPath{
     33     #define pa pair<int,int>
     34     #define mp(a,b) make_pair(a,b)
     35     priority_queue< pa, vector< pa >, greater< pa > >q;
     36     int head[N], nxt[N], to[N], len[N], dis[N], En;
     37     bool vis[N];
     38     void add_edge(int u,int v,int w) {
     39         ++En; to[En] = v; len[En] = w; nxt[En] = head[u]; head[u] = En;
     40         ++En; to[En] = u; len[En] = w; nxt[En] = head[v]; head[v] = En;
     41     }
     42     void dijkstra() {
     43         for (int i=1; i<=n; ++i) dis[i] = INF, vis[i] = false;
     44         dis[1] = 0;
     45         q.push(mp(dis[1],1));
     46         while (!q.empty()) {
     47             pa now = q.top(); q.pop();
     48             int u = now.second;
     49             if (vis[u]) continue;
     50             vis[u] = true;
     51             for (int i=head[u]; i; i=nxt[i]) {
     52                 int v = to[i];
     53                 if (dis[v] > dis[u] + len[i]) {
     54                     fa[v] = u;
     55                     dis[v] = dis[u] + len[i];
     56                     q.push(mp(dis[v], v)); // 居然写成了mp(v,dis[v])!!! 
     57                 }
     58             }
     59         }
     60     }
     61 }
     62 namespace Tree_Chain{
     63     int IIIII;
     64     int siz[N], son[N], bel[N], deth[N];
     65     vector<int> T[N];
     66     void dfs1(int u) {
     67         siz[u] = 1;
     68         deth[u] = deth[fa[u]] + 1;
     69         for (int sz=T[u].size(),i=0; i<sz; ++i) {
     70             int v = T[u][i];
     71             if (v == fa[u]) continue;
     72             dfs1(v);
     73             siz[u] += siz[v];
     74             if (!son[u] || siz[v] > siz[son[u]]) son[u] = v;
     75         }
     76     }
     77     void dfs2(int u,int top) {
     78         bel[u] = top;
     79         if (!son[u]) return;
     80         dfs2(son[u], top);
     81         for (int sz=T[u].size(),i=0; i<sz; ++i) {
     82             int v = T[u][i];
     83             if (v == fa[u] || v == son[u]) continue;
     84             dfs2(v, v);
     85         }
     86     }
     87     int LCA(int u,int v) {
     88         while (bel[u] != bel[v]) {
     89             if (deth[bel[u]] < deth[bel[v]]) swap(u, v);
     90             u = fa[bel[u]];
     91         }
     92         if (deth[u] < deth[v]) return u;
     93         return v;
     94     }
     95     void Main() {
     96         for (int i=2; i<=n; ++i) T[fa[i]].push_back(i);
     97         dfs1(1);
     98         dfs2(1, 1);
     99     }
    100 }
    101 using namespace ShortestPath;
    102 using namespace Tree_Chain;
    103 
    104 int find(int x) {
    105     return x == far[x] ? x : far[x] = find(far[x]);
    106 }
    107 void Merge(int u,int v) {
    108     u = find(u), v = find(v);
    109     if (u != v) far[u] = v;
    110 }
    111 void update(int u,int lca,int v) {
    112     u = find(u);
    113     int x = fa[u];
    114     while (deth[u] > deth[lca]) {
    115         ans[u] = v; Merge(u, x);
    116         u = find(u); x = fa[u];
    117     }
    118 }
    119 int main() {
    120     n = read(); int m = read();
    121     for (int i=1; i<=m; ++i) {
    122         int u = read(), v = read(), w = read();
    123         add_edge(u, v, w);
    124     }
    125 
    126     ShortestPath::dijkstra();
    127     Tree_Chain::Main();
    128     
    129     int cnt = 0;
    130     for (int u=1; u<=n; ++u) {
    131         for (int i=head[u]; i; i=nxt[i]) {
    132             int v = to[i];
    133             if (v > u && u != fa[v] && v != fa[u]) 
    134                 e[++cnt] = Edge(u, v, dis[u] + dis[v] + len[i], LCA(u,v)); // e[i].w,zz的减了一个dis[lca] 
    135         }
    136     }
    137     for (int i=1; i<=n; ++i) far[i] = i, ans[i] = INF;
    138     sort(e + 1, e + cnt + 1);
    139     for (int i=1; i<=cnt; ++i) {
    140         update(e[i].u, e[i].lca, e[i].w);
    141         update(e[i].v, e[i].lca, e[i].w);
    142     }
    143     for (int i=2; i<=n; ++i) 
    144         if (ans[i] == INF) puts("-1");
    145         else printf("%d
    ",ans[i] - dis[i]);
    146     return 0;
    147 }
  • 相关阅读:
    最近几个月的感想
    Fortran 入门——C#调用Fortran DLL
    Fortran 入门——函数调用
    JQueryAjax初体验和一点感想
    【HDU】1796 How many integers can you find
    【SGU】476 Coach's Trouble
    【HDU】2204 Eddy's爱好
    【POJ】1091 跳蚤
    【URAL】1091 Tmutarakan Exams
    【ZOJ】2836 Number Puzzle
  • 原文地址:https://www.cnblogs.com/mjtcn/p/9621232.html
Copyright © 2011-2022 走看看