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\n", mst);
173             } else {
174                 int tmp = find(edge[i].u, edge[i].v);
175                 printf("%I64d\n", mst-tmp+edge[i].val);
176             }
177         }
178     }
179     return 0;
180 }

 

转载于:https://www.cnblogs.com/yohaha/p/5084515.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值