BZOJ1977: [BeiJing2010组队]次小生成树 Tree

1977: [BeiJing2010组队]次小生成树 Tree

Time Limit: 10 Sec  Memory Limit: 512 MB
Submit: 3514  Solved: 941
[Submit][Status][Discuss]

Description

小 C 最近学了很多最小生成树的算法,Prim 算法、Kurskal 算法、消圈算法等等。 正当小 C 洋洋得意之时,小 P 又来泼小 C 冷水了。小 P 说,让小 C 求出一个无向图的次小生成树,而且这个次小生成树还得是严格次小的,也就是说: 如果最小生成树选择的边集是 EM,严格次小生成树选择的边集是 ES,那么需要满足:(value(e) 表示边 e的权值) 这下小 C 蒙了,他找到了你,希望你帮他解决这个问题。

Input

第一行包含两个整数N 和M,表示无向图的点数与边数。 接下来 M行,每行 3个数x y z 表示,点 x 和点y之间有一条边,边的权值为z。

Output

包含一行,仅一个数,表示严格次小生成树的边权和。(数据保证必定存在严格次小生成树)

Sample Input

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

Sample Output

11

HINT

数据中无向图无自环; 50% 的数据N≤2 000 M≤3 000; 80% 的数据N≤50 000 M≤100 000; 100% 的数据N≤100 000 M≤300 000 ,边权值非负且不超过 10^9 。

Source

 

【题解】

非严格次小生成树:求得MST,枚举加哪一条边,删除环上的最大边。

严格次小生成树:若最大边 = 加入的边,那么找不等于最大边的次大边

很多细节,见代码

求一条路径上最大边次大边时,用lca把他们拆成两条链求,更方便

由于INF设小了WA了一发

由于忘记在链上蹦跶了,WA了两发

我的AC记录啊。。。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cstdlib>
  5 #include <algorithm>
  6 #include <queue>
  7 #include <vector>
  8 #include <map>
  9 #include <string> 
 10 #include <cmath> 
 11 #define min(a, b) ((a) < (b) ? (a) : (b))
 12 #define max(a, b) ((a) > (b) ? (a) : (b))
 13 #define abs(a) ((a) < 0 ? (-1 * (a)) : (a))
 14 template<class T>
 15 inline void swap(T &a, T &b)
 16 {
 17     T tmp = a;a = b;b = tmp;
 18 }
 19 inline void read(long long &x)
 20 {
 21     x = 0;char ch = getchar(), c = ch;
 22     while(ch < '0' || ch > '9') c = ch, ch = getchar();
 23     while(ch <= '9' && ch >= '0') x = x * 10 + ch - '0', ch = getchar();
 24     if(c == '-') x = -x;
 25 }
 26 
 27 const long long INF = 0x3f3f3f3f3f3f3f3f;
 28 const long long MAXN = 500000 + 10;
 29 const long long MAXM = 500000 + 10;
 30 
 31 long long u[MAXM],v[MAXM],w[MAXM],cnt[MAXM],n,m,fa[MAXN],tot,f1,f2,M,vis[MAXM];
 32 long long cmp(long long a, long long b)
 33 {
 34     return w[a] < w[b];
 35 } 
 36 long long find(long long x)
 37 {
 38     return x == fa[x] ? x : fa[x] = find(fa[x]);
 39 }
 40 struct Edge
 41 {
 42     long long u,v,w,nxt;
 43     Edge(long long _u, long long _v, long long _w, long long _nxt){u = _u;v = _v;w = _w;nxt = _nxt;}
 44     Edge(){}
 45 }edge[MAXN << 1];
 46 long long head[MAXN], cntt;
 47 inline void insert(long long a, long long b, long long c)
 48 {
 49     edge[++ cntt] = Edge(a,b,c,head[a]);
 50     head[a] = cntt;
 51 } 
 52 
 53 //p[0]表示跳到哪个节点,p[1]表示最大值,p[2]表示次大值 
 54 long long p[3][30][MAXN], deep[MAXN];
 55 void dfs(long long x, long long pre)
 56 {
 57     for(long long pos = head[x];pos;pos = edge[pos].nxt)
 58     {
 59         long long v = edge[pos].v;
 60         if(v == pre) continue;
 61         p[0][0][v] = x, p[1][0][v] = edge[pos].w;deep[v] = deep[x] + 1, dfs(v, x);
 62     }
 63 }
 64 void yuchuli()
 65 {
 66     memset(p[1], -1, sizeof(p[1]));
 67     memset(p[2], -1, sizeof(p[2]));
 68     dfs(1, -1);
 69     for(M = 0;(1 << M) <= n;++ M); -- M;
 70     for(long long i = 1;i <= M;++ i) 
 71         for(long long j = 1;j <= n;++ j)
 72             p[0][i][j] = p[0][i - 1][p[0][i - 1][j]];
 73     for(long long i = 1;i <= M;++ i)
 74         for(long long j = 1;j <= n;++ j)
 75             if(deep[j] >= (1 << i)) 
 76             {
 77                 long long tmp1 = p[1][i - 1][j], tmp2 = p[1][i - 1][p[0][i - 1][j]];
 78                 if(tmp1 == tmp2) p[2][i][j] = max(p[2][i - 1][j], p[2][i - 1][p[0][i - 1][j]]), p[1][i][j] = tmp1;
 79                 else if(tmp1 > tmp2) p[2][i][j] = max(tmp2, p[2][i - 1][j]), p[1][i][j] = tmp1;
 80                 else p[2][i][j] = max(tmp1, p[2][i - 1][p[0][i - 1][j]]), p[1][i][j] = tmp2;
 81             }
 82 }
 83 long long LCA(long long u, long long v)
 84 {
 85     if(deep[u] < deep[v]) swap(u, v);
 86     for(long long i = M;i >= 0;-- i)
 87         if(deep[u] >= deep[v] + (1 << i))
 88             u = p[0][i][u];
 89     if(u == v) return u;
 90     for(long long i = M;i >= 0;-- i)
 91         if(p[0][i][u] != p[0][i][v])
 92             u = p[0][i][u], v = p[0][i][v];
 93     return p[0][0][u];
 94 }
 95 //v为lca 
 96 void lian(long long &ma, long long &cima, long long u, long long v)
 97 {
 98     ma = cima = -1;
 99     for(long long i = M;i >= 0;-- i)
100         if(deep[u] >= deep[v] + (1 << i))
101         {
102             if(ma < p[1][i][u]) cima = max(ma, p[2][i][u]), ma = p[1][i][u];
103             else if(ma > p[1][i][u]) cima = max(cima, p[1][i][u]);
104             else cima = max(cima, p[2][i][u]);
105             u = p[0][i][u];
106         }
107 }
108 
109 void find(long long &ma, long long &cima, long long u, long long v)
110 {
111     long long lca = LCA(u, v);
112     long long lma, lcima, rma, rcima;
113     lian(lma, lcima, u, lca), lian(rma, rcima, v, lca);
114     ma = max(lma, rma);
115     if(lma > rma) cima = max(rma, lcima);
116     else if(lma < rma) cima = max(lma, rcima);
117     else cima = max(lcima, rcima);
118 }
119 
120 long long ans, ans2;
121 int main()
122 {
123     read(n), read(m);
124     for(long long i = 1;i <= m;++ i) cnt[i] = i, read(u[i]), read(v[i]), read(w[i]);
125     for(long long i = 1;i <= n;++ i) fa[i] = i;
126     std::sort(cnt + 1, cnt + 1 + m, cmp);
127     for(long long i = 1;i <= m;++ i)
128     {
129         f1 = find(u[cnt[i]]), f2 = find(v[cnt[i]]);
130         if(f1 == f2) continue;
131         ++ tot;insert(u[cnt[i]], v[cnt[i]], w[cnt[i]]), insert(v[cnt[i]], u[cnt[i]], w[cnt[i]]);
132         fa[f1] = f2; vis[cnt[i]] = 1;ans += w[cnt[i]];
133         if(tot == n - 1) break;
134     }
135     yuchuli();ans2 = INF;
136     for(long long i = 1;i <= m;++ i)
137     {
138         if(vis[i]) continue;
139         long long ma,cima;
140         find(ma, cima, u[i], v[i]);
141         if(w[i] != ma) ans2 = min(ans2, ans + (w[i] - ma));
142         else ans2 = min(ans2, ans + (w[i] - cima));
143     }
144     printf("%lld\n", ans2);
145     return 0;
146 }
BZOJ1977

 

posted @ 2018-01-29 16:20  嘒彼小星  阅读(197)  评论(0编辑  收藏  举报