zoukankan      html  css  js  c++  java
  • BZOJ 2001: [Hnoi2010]City 城市建设

    2001: [Hnoi2010]City 城市建设

    Time Limit: 20 Sec  Memory Limit: 162 MB
    Submit: 1132  Solved: 555
    [Submit][Status][Discuss]

    Description

    PS国是一个拥有诸多城市的大国,国王Louis为城市的交通建设可谓绞尽脑汁。Louis可以在某些城市之间修建道路,在不同的城市之间修建道路需要不同的花费。Louis希望建造最少的道路使得国内所有的城市连通。但是由于某些因素,城市之间修建道路需要的花费会随着时间而改变,Louis会不断得到某道路的修建代价改变的消息,他希望每得到一条消息后能立即知道使城市连通的最小花费总和, Louis决定求助于你来完成这个任务。

    Input

    文件第一行包含三个整数N,M,Q,分别表示城市的数目,可以修建的道路个数,及收到的消息个数。 接下来M行,第i+1行有三个用空格隔开的整数Xi,Yi,Zi(1≤Xi,Yi≤n, 0≤Zi≤50000000),表示在城市Xi与城市Yi之间修建道路的代价为Zi。接下来Q行,每行包含两个数k,d,表示输入的第k个道路的修建代价修改为d(即将Zk修改为d)。

    Output

    输出包含Q行,第i行输出得知前i条消息后使城市连通的最小花费总和。

    Sample Input

    5 5 3
    1 2 1
    2 3 2
    3 4 3
    4 5 4
    5 1 5
    1 6
    1 1
    5 3

    Sample Output

    14
    10
    9

    HINT

    【数据规模】 对于20%的数据, n≤1000,m≤6000,Q≤6000。 有20%的数据,n≤1000,m≤50000,Q≤8000,修改后的代价不会比之前的代价低。 对于100%的数据, n≤20000,m≤50000,Q≤50000。

    Source

     
    [Submit][Status][Discuss]

    十分懵逼的一道CDQ分治。

    solve(l,r) 解决l到r区间内的修改及询问。

    边界:l==r,可以直接做最小生成树得到答案。

    其他:递归之前,需要在当前层进行两个操作:

    contraction 求出所有的必须边,并直接把必须边加入答案,之后不再考虑;顺道把必须边连接的两点永久合并。

    reduction 求出所有的不可能边,并直接把不可能边删除,之后不再考虑。

    把所有待修改的边权值设为-inf,做最小生成树,在MST上的非待修改边都是必须边。

    把所有待修改的边权值设为+inf,做最小生成树,不在MST上的非待修改边都是不可能边。

    进行两个操作之后,图的规模会缩小,也许是缩小一半,不造,这个太玄学,大爷都不会。

      1 #include <bits/stdc++.h>
      2 
      3 inline int getC(void) {
      4     static const int siz = 1024;
      5     
      6     static char buf[siz];
      7     static char *hd = buf + siz;
      8     static char *tl = buf + siz;
      9     
     10     if (hd == tl)
     11         fread(hd = buf, 1, siz, stdin);
     12     
     13     return int(*hd++);
     14 }
     15 
     16 inline int getI(void) {
     17     register int ret = 0;
     18     register int neg = false;
     19     register int bit = getC();
     20     
     21     for (; bit < 48; bit = getC())
     22         if (bit == '-')neg ^= true;
     23 
     24     for (; bit > 47; bit = getC())
     25         ret = ret * 10 + bit - '0';
     26     
     27     return neg ? -ret : ret;
     28 }
     29 
     30 typedef long long lnt;
     31 
     32 const int inf = 1e9;
     33 const int maxn = 20005;
     34 const int maxm = 50005;
     35 
     36 int N, M, Q;
     37 
     38 int a[maxm];
     39 int c[maxm];
     40 
     41 int sum[maxn];
     42 
     43 lnt ans[maxm];
     44 
     45 struct edge {
     46    int x, y, w, p;
     47    
     48    inline friend bool operator < 
     49    (const edge &a, const edge &b) {
     50        return a.w < b.w;
     51    }
     52 }e[25][maxm], d[maxm], b[maxm];
     53 
     54 struct edit {
     55     int x, y;
     56 }q[maxm];
     57 
     58 int fa[maxn];
     59 
     60 int find(int u) {
     61     return fa[u] == u ? u : fa[u] = find(fa[u]);
     62 }
     63 
     64 inline void clear(int t) {
     65     for (int i = 1; i <= t; ++i)
     66         fa[d[i].x] = d[i].x,
     67         fa[d[i].y] = d[i].y;
     68 }
     69 
     70 inline void merge(int x, int y) {
     71     fa[y] = x;
     72 }
     73 
     74 inline void contraction(int &t, lnt &cnt) {
     75     clear(t); int tmp = 0;
     76     std::sort(d + 1, d + 1 + t);
     77     
     78     for (int i = 1; i <= t; ++i)
     79         if (find(d[i].x) != find(d[i].y))
     80             merge(find(d[i].x), find(d[i].y)), b[++tmp] = d[i];
     81    
     82     for (int i = 1; i <= tmp; ++i)
     83         fa[b[i].x] = b[i].x,
     84         fa[b[i].y] = b[i].y;
     85     
     86     for (int i = 1; i <= tmp; ++i) 
     87         if (b[i].w != -inf && find(b[i].x) != find(b[i].y))
     88             merge(find(b[i].x), find(b[i].y)), cnt += b[i].w;
     89     
     90     tmp = 0;
     91     
     92     for (int i = 1; i <= t; ++i)
     93         if (find(d[i].x) != find(d[i].y)) {
     94             b[++tmp] = d[i];
     95             c[d[i].p] = tmp;
     96             b[tmp].x = find(d[i].x);
     97             b[tmp].y = find(d[i].y);
     98         }
     99         
    100     for (int i = 1; i <= tmp; ++i)d[i] = b[i];
    101     
    102     t = tmp;
    103 }
    104 
    105 inline void reduction(int &t) {
    106     clear(t); int tmp = 0;
    107     std::sort(d + 1, d + 1 + t);
    108     
    109     for (int i = 1; i <= t; ++i)
    110         if (find(d[i].x) != find(d[i].y)) {
    111             merge(find(d[i].x), find(d[i].y));
    112             b[++tmp] = d[i];
    113             c[d[i].p] = tmp;
    114         }
    115         else if (d[i].w == inf) {
    116             b[++tmp] = d[i];
    117             c[d[i].p] = tmp;
    118         }
    119     
    120     for (int i = 1; i <= tmp; ++i)d[i] = b[i];
    121     
    122     t = tmp;
    123 }
    124 
    125 void solve(int l, int r, int now, lnt cnt) {
    126     int t = sum[now];
    127     
    128     if (l == r)a[q[l].x] = q[l].y;
    129     
    130     for (int i = 1; i <= t; ++i)
    131         e[now][i].w = a[e[now][i].p];
    132     
    133     for (int i = 1; i <= t; ++i)
    134         d[i] = e[now][i], c[d[i].p] = i;
    135         
    136     if (l == r) {
    137         ans[l] = cnt; clear(t);
    138         std::sort(d + 1, d + 1 + t);
    139         for (int i = 1; i <= t; ++i)
    140             if (find(d[i].x) != find(d[i].y))
    141                 merge(find(d[i].x), find(d[i].y)), ans[l] += d[i].w;
    142         return;
    143     }
    144     
    145     for (int i = l; i <= r; ++i)
    146         d[c[q[i].x]].w = -inf;
    147         
    148     contraction(t, cnt);
    149     
    150     for (int i = l; i <= r; ++i)
    151         d[c[q[i].x]].w = inf;
    152         
    153     reduction(t);
    154     
    155     for (int i = 1; i <= t; ++i)
    156         e[now + 1][i] = d[i];
    157         
    158     sum[now + 1] = t;
    159     
    160     int mid = (l + r) >> 1;
    161     
    162     solve(l, mid, now + 1, cnt);
    163     solve(mid + 1, r, now + 1, cnt);
    164 }
    165 
    166 signed main(void) {
    167     N = getI();
    168     M = getI();
    169     Q = getI();
    170     
    171     for (int i = 1; i <= M; ++i) {
    172         e[0][i].p = i;
    173         e[0][i].x = getI();
    174         e[0][i].y = getI();
    175         e[0][i].w = getI();
    176         a[i] = e[0][i].w;
    177     }
    178     
    179     for (int i = 1; i <= Q; ++i) {
    180         q[i].x = getI();
    181         q[i].y = getI();
    182     }
    183     
    184     sum[0] = M;
    185     
    186     solve(1, Q, 0, 0);
    187     
    188     for (int i = 1; i <= Q; ++i)
    189         printf("%lld
    ", ans[i]);
    190 }

    @Author: YouSiki

  • 相关阅读:
    浅谈localStorage本地存储
    前端代码中经常遇到的问题
    http状态码
    Transition 所支持的css属性
    ie8下的透明 问题
    #event.initMouseEvent
    svg 文字
    前端工作流程转变
    理解javascript 回调函数
    不要被npm、NodeJs、npm、webpack、vue-cli 这些名词搞晕
  • 原文地址:https://www.cnblogs.com/yousiki/p/6243696.html
Copyright © 2011-2022 走看看