NOIP2013 D1T3 貨車運輸 zz恥辱記
阿新 • • 發佈:2018-11-11
目錄
先來證明下lemma: 圖上2點間最小邊權最大的路徑一定在MST上
感性理解下:
每次kruskal algo都連線最大的不成環邊
此時有2個未聯通的聯通塊被連起來.
那麼考慮u, v兩點的聯通塊 : 它們並起來時選的邊最大. (將比這條邊大的邊加入生成樹不能使得u,v聯通)
這個思想是kruskal重構樹的基礎(每個聯通塊選取一個代表點)
sb題, 但是做的噎屎了, 花了1.5h
我還是應該熟悉一下 最小生成樹, 樹上倍增和並查集
2個sb錯誤:
- 見code l58
並查集沒初始化
code
//file headers start #include<bits/stdc++.h> using namespace std; #define rep(i, _st, _ed) for(register int i = (_st); i <= (_ed); ++i) int read(){ int f = 1, ans = 0; char c = getchar(); while(!isdigit(c)) { if(c == '-') f = -1; c = getchar(); } while(isdigit(c)) { ans = ans * 10 + c - '0'; c = getchar(); } return ans * f; } void put(int num) { printf("%d\n", num); } void testread() { while(1) { int k = read(); put(k); if(!k) break;}} const int maxn = 10005, maxm = 50005; struct graph{ int v, nxt, w; }edge[maxm*2]; int head[maxn], n, m; void adde(int u, int v, int w){ static int cnt = 0; edge[++cnt].v = v, edge[cnt].w = w; edge[cnt].nxt = head[u], head[u] = cnt; } //file headers end struct ee{ int u, v, w; bool operator<(const ee &rhs)const{return w>rhs.w;} }e[maxm]; int fa[maxn]; int find(int u) {return (fa[u]==u)?u:fa[u] = find(fa[u]);} int dep[maxn], f[21][maxn], vis[maxn], d[21][maxn]; void dfs(int u, int fa){ dep[u] = dep[fa]+1, vis[u] = 1; f[0][u] = fa; for(int i = head[u]; i; i = edge[i].nxt){ if(edge[i].v!=fa)dfs(edge[i].v, u), d[0][edge[i].v] = edge[i].w; } } int lcapth(int u, int v){ int ans = 1e9; if(dep[u] < dep[v]) swap(u, v); int i = 20; for(i = 20; i >= 0; i--) if(dep[f[i][u]] >= dep[v]) ans = min(ans, d[i][u]), u = f[i][u]; if(u == v) return ans; for(i = 20; i >= 0; i--){ if(f[i][u] != f[i][v] ) { //omg 這裡是f[i][u]不是dep[f[i][u]] ans = min(ans, d[i][u]), ans = min(ans, d[i][v]); u = f[i][u], v = f[i][v]; } } return min(ans, min(d[0][u], d[0][v])); } signed main(){ //fileop("test"); n = read(), m = read(); rep(i, 1, m) { int u = read(), v = read(), w = read(); e[i].u = u, e[i].v = v, e[i].w = w; } sort(e+1, e+m+1); rep(i, 1, n) fa[i] = i; //don't forget initialize bcj!!! rep(i, 1, m){ if(find(e[i].v) != find(e[i].u)){ adde(e[i].u, e[i].v, e[i].w), adde(e[i].v, e[i].u, e[i].w); fa[find(e[i].v)] = find(e[i].u); //printf("%d %d\n", e[i].u, e[i].v); } } rep(i, 1, n) if(vis[i] == 0) dfs(i, 0), f[0][i] = i, d[0][i] = 1e9; //root should form self loop rep(i, 1, 20)rep(j, 1, n) f[i][j] = f[i-1][f[i-1][j]], d[i][j] = min(d[i-1][j], d[i-1][f[i-1][j] ]); int q = read(); while(q--){ int u = read(), v = read(); if(find(u) == find(v)) put(lcapth(u, v)); else put(-1); } return 0; } /* 5 7 4 3 4440 3 1 22348 1 3 28368 2 4 25086 5 3 6991 4 3 10638 3 1 11106 4 4 5 1 3 5 4 2 5 */