zoukankan      html  css  js  c++  java
  • Codeforces 835F Roads in the Kingdom

    题目传送门

      传送点I

      传送点II

      传送点III

    题目大意

       给定一颗基环树,要求删去其中一条边,使得剩下的图形是一棵树,并且最长路的长度最短,求最长路的最短长度。

      路径可以分为两部分:跨过环 和 在树内部。

      要删除一条边,使图形变为一棵树,那么只能删去环上的一条边,因此,我们无法改变第二部分的路径,但是可以改变第一部分。

      对于第二部分可以通过两次搜索或者树形动态规划解决。

      对于第一部分,考虑枚举删去环上的一条边。但是发现仍然不太方便处理,因为不好维护环上的信息。仍然考虑剖环成链。

      假设环的大小为$k$,从剖点开始依次将所有点标号1到$k$。

      当一条边被删除后,第二部分可能成为答案的情况有两种:

    1. 不跨过剖点和被删边的路径
    2. 跨过剖点但不经过被删边的路径

      因此考虑维护一些数组。

    1. 在$1, 2, cdots, i$及其所在的树中的最长路。
    2. 从$1$开始,到$1, 2, cdots, i$及其所在的树中的最长路。
    3. 在$k, k - 1, cdots, i$及其所在的树中的最长路。
    4. 从$k$开始,到$k, k - 1, cdots, i$及其所在的树中的最长路。

      这四个部分都可以线性预处理出来。然后枚举删掉的环边就能统计第一部分的答案。

    Code

      1 /**
      2  * Codeforces
      3  * Problem#835F
      4  * Accepted
      5  * Time: 155ms
      6  * Memory: 27100k
      7  */ 
      8 #include <bits/stdc++.h>
      9 #ifndef WIN32
     10 #define Auto "%lld"
     11 #else
     12 #define Auto "%I64d"
     13 #endif
     14 using namespace std;
     15 typedef bool boolean;
     16 
     17 typedef class Edge {
     18     public:
     19         int ed, nx, w;
     20 
     21         Edge(int ed = 0, int nx = 0, int w = 0):ed(ed), nx(nx), w(w) {    }
     22 }Edge;
     23 
     24 typedef class MapManager {
     25     public:
     26         int ce;
     27         int* h;
     28         Edge* es;
     29 
     30         MapManager() {    }
     31         MapManager(int n, int m):ce(-1) {
     32             h = new int[(n + 1)];
     33             es = new Edge[(m + 1)];
     34             memset(h, -1, sizeof(int) * (n + 1));
     35         }
     36 
     37         void addEdge(int u, int v, int w) {
     38             es[++ce] = Edge(v, h[u], w);
     39             h[u] = ce;
     40         }
     41 
     42         Edge& operator [] (int pos) {
     43             return es[pos];
     44         }
     45 }MapManager;
     46 
     47 #define ll long long
     48 
     49 const signed ll llf = (signed ll) ((~0ull) >> 1);
     50 
     51 int n;
     52 int ccir, cc;
     53 MapManager g;
     54 stack<int> s;
     55 boolean *vis, *icir;
     56 int *cir, *nw;
     57 ll *ap[2], *cp[2], *dep, *dis;
     58 
     59 inline void init() {
     60     scanf("%d", &n);
     61     vis = new boolean[(n + 1)];
     62     icir = new boolean[(n + 1)];
     63     cir = new int[(n + 1)];
     64     nw = new int[(n + 1)];
     65     dep = new ll[(n + 1)];
     66     dis = new ll[(n + 1)];
     67     for (int i = 0; i < 2; i++) {
     68         ap[i] = new ll[(n + 1)];
     69         cp[i] = new ll[(n + 1)];
     70     }
     71     g = MapManager(n, n << 1);
     72     memset(vis, false, sizeof(boolean) * (n + 1));
     73     memset(icir, false, sizeof(boolean) * (n + 1));
     74     for (int i = 1, u, v, w; i <= n; i++) {
     75         scanf("%d%d%d", &u, &v, &w);
     76         g.addEdge(u, v, w);
     77         g.addEdge(v, u, w);
     78     }
     79 }
     80 
     81 boolean getLoop(int p, int fa) {
     82     if (vis[p]) {
     83         ccir = 0;
     84         int cur = 0;
     85         do {
     86             cur = s.top();
     87             s.pop();
     88             icir[cur] = true;
     89             cir[ccir++] = cur;
     90             cc = ccir - 1;
     91         } while (cur != p);
     92         return true;
     93     }
     94     vis[p] = true;
     95     s.push(p);
     96     for (int i = g.h[p]; ~i; i = g[i].nx) {
     97         int e = g[i].ed;
     98         if (e == fa)    continue;
     99         if (getLoop(e, p)) {
    100             if (icir[p]) {
    101                 nw[cc] = g[i].w;
    102                 cc = (cc + 1) % ccir;
    103             }
    104             return true;
    105         } 
    106     }
    107     s.pop();
    108     return false;
    109 }
    110 
    111 void dfs(int p, int fa, ll dep, int& fn, ll& fd) {
    112     if (dep > fd)
    113         fd = dep, fn = p;
    114     for (int i = g.h[p]; ~i; i = g[i].nx) {
    115         int e = g[i].ed;
    116         if (e == fa || icir[e])    continue;
    117         dfs(e, p, dep + g[i].w, fn, fd);
    118     }
    119 }
    120 
    121 inline void solve() {
    122     getLoop(1, 0);
    123     ll fixedd = 0;
    124 //    for (int i = 0; i < ccir; i++)
    125 //        cerr << cir[i] << " ";
    126 //    cerr << endl;
    127 //    for (int i = 0; i < ccir; i++)
    128 //        cerr << nw[i] << " ";
    129 //    cerr << endl;
    130     for (int i = 0, fn, fbn; i < ccir; i++) {
    131         fn = -1, dep[i] = 0;
    132         dep[i] = 0, dfs(cir[i], 0, 0, fn, dep[i]);
    133         if (~fn)
    134             icir[cir[i]] = false, dfs(fn, 0, 0, fbn, fixedd), icir[cir[i]] = true;
    135     }
    136     dis[0] = 0;
    137     for (int i = 1; i < ccir; i++)
    138         dis[i] = nw[i - 1];
    139     for (int i = 1; i < ccir; i++)
    140         dis[i] += dis[i - 1];
    141     ll mi = dep[0];
    142     ap[0][0] = -llf, cp[0][0] = dep[0];
    143     for (int i = 1; i < ccir; i++) {
    144         ap[0][i] = max(ap[0][i - 1], dep[i] + dis[i] + mi);
    145         mi = max(mi, dep[i] - dis[i]);
    146         cp[0][i] = max(cp[0][i - 1], dep[i] + dis[i]);
    147     }
    148     mi = dep[ccir - 1] + dis[ccir - 1];
    149     ap[1][ccir - 1] = -llf, cp[1][ccir - 1] = dep[ccir - 1];
    150     for (int i = ccir - 2; ~i; i--) {
    151         ap[1][i] = max(ap[1][i + 1], dep[i] - dis[i] + mi);
    152         mi = max(mi, dep[i] + dis[i]);
    153         cp[1][i] = max(cp[1][i + 1], dep[i] + dis[ccir - 1] - dis[i]);
    154     }
    155     ll ans = ap[0][ccir - 1];
    156     for (int i = 0; i < ccir - 1; i++)
    157         ans = min(max(max(ap[0][i], ap[1][i + 1]), cp[0][i] + cp[1][i + 1] + nw[ccir - 1]), ans);
    158     printf(Auto, max(ans, fixedd));
    159 }
    160 
    161 int main() {
    162     init();
    163     solve();
    164     return 0;
    165 }
  • 相关阅读:
    centos6.8安装JDK1.8
    尚硅谷 ActiveMQ
    Spring 注解版-事务实现
    nginx实现动静分离
    C/C++ 位域
    大小端模式
    C++find函数
    C++ transform
    C++ string的大小写转换
    C++ pair用法
  • 原文地址:https://www.cnblogs.com/yyf0309/p/9250520.html
Copyright © 2011-2022 走看看