zoukankan      html  css  js  c++  java
  • 洛谷P1399 快餐店

    题意:在基环树上找一点,使得这个点到所有点的距离最大值最小。这个点可以在某条边上。

    解:很容易想到找出直径然后/2对吧...这里的直径是指任意两点间最短距离的最大值。

    然而我这个SB冥思苦想了半天之后想到了一个傻逼绝伦的做法:枚举边!

    这个点一定在某条边上。

    所以知道边的两端点最长延伸多长即可。

    如果是子树里的边,很显然下面那个点就是子树内最长链。而上面那个点就是子树外最长链或深度 + 根节点在环上最长延伸距离

    如果是环上的边,就是两端点子树最长链或者环上延伸的最长距离

    值得注意的是,这两个"环上最长延伸距离"并不是一样的。

    因为前者只有一个点在环上,没有别的环上的点跟它竞争。

    而后者要跟环上另一个点相互竞争。所以还要分两种情况。

    具体实现上,首先找环,然后每个子树做两次树形DP,第二次是二次扫描与换根法。

    然后把环的信息提取出来DP,利用单调队列来求最长延伸距离,反正我写了4个......

    最后枚举边判定。

    反正就是仔细写,耐心Debug...

    (为什么别人1k就能A而我要5k啊...)

      1 #include <cstdio>
      2 #include <algorithm>
      3 #include <stack>
      4 #include <cstring>
      5 
      6 typedef long long LL;
      7 const int N = 200010;
      8 
      9 struct Edge {
     10     int nex, v;
     11     LL len;
     12 }edge[N << 1]; int top = 1;
     13 
     14 int e[N], n, cir[N], tc, p[N], head, tail, fr[N], nex[N], pre[N];
     15 std::stack<int> S;
     16 bool vis[N], is_cir[N];
     17 LL d[N], len1[N], len2[N], lenup[N], dis[N], p2[N], sum[N], Long[N], Long_l[N], Long_r[N];
     18 
     19 inline void add(int x, int y, LL z) {
     20     top++;
     21     edge[top].v = y;
     22     edge[top].len = z;
     23     edge[top].nex = e[x];
     24     e[x] = top;
     25     return;
     26 }
     27 
     28 void Df(int x, int f) {
     29     vis[x] = 1;
     30     S.push(x);
     31     for(int i = e[x]; i && !vis[0]; i = edge[i].nex) {
     32         int y = edge[i].v;
     33         if(y == f) {
     34             continue;
     35         }
     36         if(vis[y]) {
     37             vis[0] = 1;
     38             while(x != y) {
     39                 x = S.top();
     40                 S.pop();
     41                 is_cir[x] = 1;
     42                 cir[++tc] = x;
     43             }
     44             return;
     45         }
     46         Df(y, x);
     47     }
     48     if(vis[0]) {
     49         return;
     50     }
     51     S.pop();
     52     vis[x] = 0;
     53     return;
     54 }
     55 
     56 void DFS_1(int x, int f, int aim) { // get d len1 len2
     57     if(!fr[x]) {
     58         fr[x] = fr[f];
     59     }
     60     for(int i = e[x]; i; i = edge[i].nex) {
     61         int y = edge[i].v;
     62         if(y == f || is_cir[y]) {
     63             if(cir[aim] == y) {
     64                 dis[aim] = edge[i].len;
     65                 nex[x] = y;
     66                 pre[y] = x;
     67             }
     68             continue;
     69         }
     70         d[y] = d[x] + edge[i].len;
     71         DFS_1(y, x, aim);
     72         if(len1[x] < len1[y] + edge[i].len) {
     73             len2[x] = len1[x];
     74             len1[x] = len1[y] + edge[i].len;
     75         }
     76         else if(len2[x] < len1[y] + edge[i].len) {
     77             len2[x] = len1[y] + edge[i].len;
     78         }
     79     }
     80     return;
     81 }
     82 
     83 void DFS_2(int x, int f) {
     84     for(int i = e[x]; i; i = edge[i].nex) {
     85         int y = edge[i].v;
     86         if(y == f || is_cir[y]) {
     87             continue;
     88         }
     89         if(len1[y] + edge[i].len == len1[x]) {
     90             lenup[y] = std::max(lenup[x], len2[x]) + edge[i].len;
     91         }
     92         else {
     93             lenup[y] = std::max(lenup[x], len1[x]) + edge[i].len;
     94         }
     95         DFS_2(y, x);
     96     }
     97     return;
     98 }
     99 
    100 int main() {
    101     int x, y;
    102     LL z, Sum = 0;
    103     double ans = 0;
    104     scanf("%d", &n);
    105     for(int i = 1; i <= n; i++) {
    106         scanf("%d%d%lld", &x, &y, &z);
    107         add(x, y, z);
    108         add(y, x, z);
    109         ans += z;
    110     }
    111     Df(1, 0);
    112 
    113     for(int i = 1; i <= tc; i++) {
    114         fr[cir[i]] = cir[i];
    115         DFS_1(cir[i], 0, (i == tc ? 1 : i + 1));
    116         DFS_2(cir[i], 0);
    117         cir[tc + i] = cir[i];
    118     }
    119     for(int i = 1; i <= tc; i++) {
    120         Sum += dis[i];
    121         dis[tc + i] = dis[i];
    122     }
    123     for(int i = 1; i <= tc * 2; i++) {
    124         sum[i] = sum[i - 1] + dis[i];
    125     }
    126 
    127     LL dt = 0;
    128     head = 1;
    129     tail = 0;
    130     for(int i = 1; i <= tc * 2; i++) {
    131         // DP
    132         while(head <= tail && sum[i] - sum[p[head]] > Sum - (sum[i] - sum[p[head]])) {
    133             head++;
    134         }
    135         dt += dis[i];
    136         if(head <= tail) {
    137             Long[cir[i]] = std::max(Long[cir[i]], p2[head] + dt);
    138         }
    139         while(head <= tail && len1[cir[i]] - dt >= p2[tail]) {
    140             tail--;
    141         }
    142         p[++tail] = i;
    143         p2[tail] = len1[cir[i]] - dt;
    144     }
    145     head = 1;
    146     tail = 0;
    147     dt = 0;
    148     for(int i = tc * 2; i >= 1; i--) {
    149         while(head <= tail && sum[p[head]] - sum[i] > Sum - (sum[p[head]] - sum[i])) {
    150             head++;
    151         }
    152         dt += dis[i + 1];
    153         if(head <= tail) {
    154             Long[cir[i]] = std::max(Long[cir[i]], p2[head] + dt);
    155         }
    156         while(head <= tail && len1[cir[i]] - dt >= p2[tail]) {
    157             tail--;
    158         }
    159         p[++tail] = i;
    160         p2[tail] = len1[cir[i]] - dt;
    161     }
    162     // -------------------------------------------------------------------------------------------------------
    163     head = 1;
    164     tail = 0;
    165     dt = 0;
    166     dis[tc * 2 + 1] = dis[1];
    167     for(int i = 1; i <= tc * 2; i++) {
    168         // DP
    169         while(head <= tail && sum[i] - sum[p[head]] > Sum - (sum[i] - sum[p[head]] + dis[i + 1])) {
    170             head++;
    171         }
    172         dt += dis[i];
    173         if(head <= tail) {
    174             Long_l[cir[i]] = std::max(Long_l[cir[i]], p2[head] + dt);
    175         }
    176         while(head <= tail && len1[cir[i]] - dt >= p2[tail]) {
    177             tail--;
    178         }
    179         p[++tail] = i;
    180         p2[tail] = len1[cir[i]] - dt;
    181     }
    182     head = 1;
    183     tail = 0;
    184     dt = 0;
    185     for(int i = tc * 2; i >= 1; i--) {
    186         while(head <= tail && sum[p[head]] - sum[i] > Sum - (sum[p[head]] - sum[i - 1])) {
    187             head++;
    188         }
    189         dt += dis[i + 1];
    190         if(head <= tail) {
    191             Long_r[cir[i]] = std::max(Long_r[cir[i]], p2[head] + dt);
    192         }
    193         while(head <= tail && len1[cir[i]] - dt >= p2[tail]) {
    194             tail--;
    195         }
    196         p[++tail] = i;
    197         p2[tail] = len1[cir[i]] - dt;
    198     }
    199     //
    200     for(int i = 2; i <= top; i += 2) {
    201         int x = edge[i].v, y = edge[i ^ 1].v;
    202         LL a, b;
    203         if(is_cir[x] && is_cir[y]) {
    204             if(nex[y] == x) {
    205                 std::swap(x, y);
    206             }
    207             a = std::max(Long_l[x], len1[x]);
    208             b = std::max(Long_r[y], len1[y]);
    209         }
    210         else {
    211             if(d[x] > d[y]) {
    212                 std::swap(x, y);
    213             }
    214             a = len1[y];
    215             b = std::max(lenup[y] - edge[i].len, d[x] + Long[fr[x]]);
    216         }
    217         if(a < b) {
    218             std::swap(a, b);
    219         }
    220         if(a >= edge[i].len + b) {
    221             ans = std::min(ans, (double)a);
    222         }
    223         else {
    224             ans = std::min(ans, (a + b + edge[i].len) / 2.0);
    225         }
    226     }
    227 
    228     printf("%.1f", ans);
    229     return 0;
    230 }
    AC代码
  • 相关阅读:
    深入理解iOS开发中的锁
    整理:iOS开发算法资料
    (二)ELK Filebeat简介
    (一)ELK 部署
    zabbix + grafana 展示
    (二)LVS介绍
    (一)集群介绍
    zabbix 监控 ESXI
    zabbix proxy 安装
    zabbix fping 监控网络质量
  • 原文地址:https://www.cnblogs.com/huyufeifei/p/10339741.html
Copyright © 2011-2022 走看看