zoukankan      html  css  js  c++  java
  • codeforces 609E. Minimum spanning tree for each edge 树链剖分

    题目链接

    给一个n个节点m条边的树, 每条边有权值, 输出m个数, 每个数代表包含这条边的最小生成树的值。

    先将最小生成树求出来, 把树边都标记。 然后对标记的边的两个端点, 我们add(u, v), add(v, u)。 对于每一次输出, 如果这条边被标记了, 那么直接输出mst的值。 否则, 加上这条边之后一定会出现一个环, 我们就把环上的最长的那条边删掉。 查询最长的那条边可以用树链剖分。

      1 #include <iostream>
      2 #include <vector>
      3 #include <cstdio>
      4 #include <cstring>
      5 #include <algorithm>
      6 #include <cmath>
      7 #include <map>
      8 #include <set>
      9 #include <string>
     10 #include <queue>
     11 #include <stack>
     12 #include <bitset>
     13 using namespace std;
     14 #define pb(x) push_back(x)
     15 #define ll long long
     16 #define mk(x, y) make_pair(x, y)
     17 #define lson l, m, rt<<1
     18 #define mem(a) memset(a, 0, sizeof(a))
     19 #define rson m+1, r, rt<<1|1
     20 #define mem1(a) memset(a, -1, sizeof(a))
     21 #define mem2(a) memset(a, 0x3f, sizeof(a))
     22 #define rep(i, n, a) for(int i = a; i<n; i++)
     23 #define fi first
     24 #define se second
     25 typedef pair<int, int> pll;
     26 const double PI = acos(-1.0);
     27 const double eps = 1e-8;
     28 const int mod = 1e9+7;
     29 const int inf = 1061109567;
     30 const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
     31 const int maxn = 2e5+5;
     32 int head[maxn*2], son[maxn], sz[maxn], deep[maxn], top[maxn], w[maxn], f[maxn], cnt, num;
     33 int maxx[maxn<<2], fa[maxn];
     34 struct node
     35 {
     36     int to, nextt;
     37 }e[maxn*2];
     38 struct ed
     39 {
     40     int u, v, id, val, mark;
     41     ed(){}
     42     ed(int u, int v, int val, int id, int mark = 0):u(u), v(v), val(val), id(id), mark(mark){}
     43 }edge[maxn];
     44 bool cmp1(ed a, ed b) {
     45     return a.id<b.id;
     46 }
     47 bool cmp2(ed a, ed b) {
     48     if(a.val == b.val)
     49         return a.id<b.id;
     50     return a.val<b.val;
     51 }
     52 void init() {
     53     mem1(head);
     54     num = cnt = 0;
     55 }
     56 void add(int u, int v, int w) {
     57     e[num].to = v, e[num].nextt = head[u], head[u] = num++;
     58 }
     59 void dfs1(int u, int fa) {
     60     sz[u] = 1;
     61     deep[u] = deep[fa]+1;
     62     son[u] = -1;
     63     f[u] = fa;
     64     for(int i = head[u]; ~i; i = e[i].nextt) {
     65         int v = e[i].to;
     66         if(v == fa)
     67             continue;
     68         dfs1(v, u);
     69         sz[u] += sz[v];
     70         if(son[u]==-1||sz[v]>sz[son[u]])
     71             son[u] = v;
     72     }
     73 }
     74 void dfs2(int u, int tp) {
     75     w[u] = ++cnt, top[u] = tp;
     76     if(~son[u])
     77         dfs2(son[u], tp);
     78     for(int i = head[u]; ~i; i = e[i].nextt) {
     79         int v = e[i].to;
     80         if(v == f[u]||v == son[u])
     81             continue;
     82         dfs2(v, v);
     83     }
     84 }
     85 void pushUp(int rt) {
     86     maxx[rt] = max(maxx[rt<<1], maxx[rt<<1|1]);
     87 }
     88 void update(int p, int val, int l, int r, int rt) {
     89     if(l == r) {
     90         maxx[rt] = val;
     91         return ;
     92     }
     93     int m = l+r>>1;
     94     if(p<=m)
     95         update(p, val, lson);
     96     else
     97         update(p, val, rson);
     98     pushUp(rt);
     99 }
    100 int query(int L, int R, int l, int r, int rt) {
    101     if(L<=l&&R>=r) {
    102         return maxx[rt];
    103     }
    104     int m = l+r>>1, ret = 0;
    105     if(L<=m)
    106         ret = max(ret, query(L, R, lson));
    107     if(R>m)
    108         ret = max(ret, query(L, R, rson));
    109     return ret;
    110 }
    111 int find(int u, int v) {
    112     int f1 = top[u], f2 = top[v], ret = 0;
    113     while(f1 != f2) {
    114         if(deep[f1]<deep[f2]) {
    115             swap(f1, f2);
    116             swap(u, v);
    117         }
    118         ret = max(ret, query(w[f1], w[u], 1, cnt, 1));
    119         u = f[f1];
    120         f1 = top[u];
    121     }
    122     if(u == v)
    123         return ret;
    124     if(deep[u]>deep[v])
    125         swap(u, v);
    126     return max(ret, query(w[son[u]], w[v], 1, cnt, 1));
    127 }
    128 int findd(int u) {
    129     return fa[u] == u?u:fa[u] = findd(fa[u]);
    130 }
    131 int main()
    132 {
    133     int t, n, u, v, val, m;
    134     while(~scanf("%d%d", &n, &m)) {
    135         init();
    136         ll mst = 0;
    137         deep[0] = 0;
    138         for(int i = 1; i<=m; i++) {
    139             scanf("%d%d%d", &u, &v, &val);
    140             edge[i] = ed(u, v, val, i);
    141         }
    142         for(int i = 1; i<=n; i++)
    143             fa[i] = i;
    144         sort(edge+1, edge+1+m, cmp2);
    145         for(int i = 1; i<=m; i++) {
    146             u = findd(edge[i].u);
    147             v = findd(edge[i].v);
    148             if(u == v)
    149                 continue;
    150             edge[i].mark = 1;
    151             fa[v] = u;
    152             mst += edge[i].val;
    153         }
    154         for(int i = 1; i<=m; i++) {
    155             if(edge[i].mark) {
    156                 add(edge[i].u, edge[i].v, edge[i].val);
    157                 add(edge[i].v, edge[i].u, edge[i].val);
    158             }
    159         }
    160         dfs1(1, 0);
    161         dfs2(1, 1);
    162         for(int i = 1; i<=m; i++) {
    163             if(deep[edge[i].u]>deep[edge[i].v]) {
    164                 swap(edge[i].u, edge[i].v);
    165             }
    166             if(edge[i].mark)
    167                 update(w[edge[i].v], edge[i].val, 1, cnt, 1);
    168         }
    169         sort(edge+1, edge+1+m, cmp1);
    170         for(int i = 1; i<=m; i++) {
    171             if(edge[i].mark) {
    172                 printf("%I64d
    ", mst);
    173             } else {
    174                 int tmp = find(edge[i].u, edge[i].v);
    175                 printf("%I64d
    ", mst-tmp+edge[i].val);
    176             }
    177         }
    178     }
    179     return 0;
    180 }
  • 相关阅读:
    Armbian hostname and WiFi configuration
    尼采的哲学
    深度学习 —— 使用 gensim 实现 word2vec
    sklearn preprocessing 数据预处理(OneHotEncoder)
    中英文对照 —— 饮食与美食
    matlab 常用机器学习算法的实现
    linux下svn常用指令
    Python创建删除文件
    php使用mysql和mysqli连接查询数据
    vsftpd配置文件详解
  • 原文地址:https://www.cnblogs.com/yohaha/p/5084515.html
Copyright © 2011-2022 走看看