首页 > 代码库 > bzoj 1977
bzoj 1977
题意:求严格的次小生成树。点n<=100000,m<=300000
思路:很容易想到先做一边最小生成树,然后枚举每条非树边(u, v, w),然后其实就是把u,v路径上小于w的最大边替换成w,对于所有的这种新树取一个权值最小的即可。。
然后就变成求u,v的最大值及次大值。。树链剖分和lct显然是可以做的。。
不过很早就知道倍增却一直没写过,今天就正好写一发。。
code:
1 /************************************************************** 2 Problem: 1977 3 User: yzcstca 4 Language: C++ 5 Result: Accepted 6 Time:2344 ms 7 Memory:35048 kb 8 ****************************************************************/ 9 10 #include<cstdio> 11 #include<iostream> 12 #include<cstring> 13 #include<cstdlib> 14 #include<cmath> 15 #include<algorithm> 16 #include<string> 17 #include<map> 18 #include<set> 19 #include<vector> 20 #include<queue> 21 #include<stack> 22 #include<ctime> 23 #define repf(i, a, b) for (int i = (a); i <= (b); ++i) 24 #define M0(x) memset(x, 0, sizeof(x)) 25 #define vii vector< pair<int, int> >::iterator 26 #define x first 27 #define y second 28 #define two(i) (1 << i) 29 using namespace std; 30 typedef long long ll; 31 typedef pair<int, int> pii; 32 const int maxn = 101001; 33 const int maxm = 301000; 34 struct oo{ 35 int u, v, w; 36 bool operator<(const oo& p) const{ 37 return w < p.w; 38 } 39 } E[maxm]; 40 vector<pii> e[maxn]; 41 int fa[maxn], intree[maxm]; 42 int n, m, ans; 43 int dep[maxn], f[maxn][20], vv[maxn][20][2]; 44 45 void init(){ 46 for (int i = 0; i < m; ++i) 47 scanf("%d%d%d", &E[i].u, &E[i].v, &E[i].w); 48 repf(i, 0, n) e[i].clear(); 49 } 50 51 52 inline int find(const int& k){ 53 return fa[k] == k ? k : fa[k] = find(fa[k]); 54 } 55 56 int vis[maxn], t[maxn]; 57 void bfs(){ 58 M0(vis); 59 queue<int> q; 60 q.push(1), dep[1] = 0, vis[1] = 1; 61 int u, v, cnt; 62 t[cnt = 1] = 1; 63 while (!q.empty()){ 64 u = q.front(); 65 q.pop(); 66 for (vii it = e[u].begin(); it != e[u].end(); ++it){ 67 if (vis[it->x]) continue; 68 dep[it->x] = dep[u] + 1; 69 f[it->x][0] = u; 70 vv[it->x][0][0] = it->y, vv[it->x][0][1] = -1; 71 q.push(it->x), vis[it->x] = 1, t[++cnt] = it->x; 72 } 73 } 74 } 75 76 void update(int v[],const int& val){ 77 if (val > v[0]) 78 swap(v[0], v[1]), v[0] = val; 79 else if (val < v[0] && val > v[1]) 80 v[1] = val; 81 } 82 83 void rmq(){ 84 int u, v; 85 repf(i, 1, n){ 86 u = t[i]; 87 for (int i = 1; i <= 17; ++i){ 88 if (two(i) > dep[u]) break; 89 v = f[u][i-1]; 90 f[u][i] = f[v][i-1]; 91 vv[u][i][0] = vv[u][i][1] = -1; 92 update(vv[u][i], vv[u][i-1][0]); 93 update(vv[u][i], vv[u][i-1][1]); 94 update(vv[u][i], vv[v][i-1][0]); 95 update(vv[u][i], vv[v][i-1][1]); 96 } 97 } 98 } 99 100 int res[2];101 void query(int u, int s, int res[]){102 for (int i = 0; i <= 17; ++i) if (s & two(i))103 update(res, vv[u][i][0]), update(res, vv[u][i][1]), u = f[u][i], s ^= two(i);104 }105 106 void work(int u, int v, const int& w){107 if (dep[u] > dep[v]) swap(u, v);108 int fu = u, fv = v, h;109 if (dep[fu] != dep[fv]){110 h = dep[fv] - dep[fu];111 for (int i = 0; i <= 17; ++i) if (h & two(i))112 h ^= two(i), fv = f[fv][i];113 }114 if (fu == fv){115 res[0] = res[1] = -1;116 query(v, dep[v] - dep[u], res);117 h = (res[0] != w) ? res[0] : res[1];118 if (h != -1) ans = min(ans, w - h);119 return;120 }121 for (int i = 17; i >= 0; --i){122 if (two(i) > dep[fu]) continue;123 if (f[fu][i] != f[fv][i])124 fu = f[fu][i], fv = f[fv][i];125 }126 fu = f[fu][0];127 res[0] = res[1] = -1;128 query(u, dep[u] - dep[fu], res);129 query(v, dep[v] - dep[fu], res);130 h = (res[0] != w) ? res[0] : res[1];131 if (h != -1) ans = min(ans, w - h);132 }133 134 void solve(){135 repf(i, 0, n) fa[i] = i;136 sort(E, E + m);137 memset(intree, 0, sizeof(int) * (m + 10));138 int u, v, fu, fv, w;139 ll mst = 0;140 repf(i, 0, m-1){141 u = E[i].u, v = E[i].v, w = E[i].w;142 fu = find(u), fv = find(v);143 if (fu != fv){144 fa[fu] = fv, intree[i] = 1;145 mst += E[i].w;146 e[u].push_back(make_pair(v, w));147 e[v].push_back(make_pair(u, w) );148 }149 }150 bfs();151 rmq();152 ans = 0x3fffffff;153 for (int i = 0; i < m; ++i) if (!intree[i])154 work(E[i].u, E[i].v, E[i].w);155 cout << mst + ans << endl;156 157 }158 159 int main(){160 // freopen("a.in", "r", stdin);161 // freopen("a.out", "w", stdout);162 while (scanf("%d%d", &n, &m) != EOF){163 init();164 solve();165 }166 return 0;167 }
bzoj 1977
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。