NOIP2013 D1T3 货车运输 zz耻辱记

目录

先来证明下lemma: 图上2点间最小边权最大的路径一定在MST上
感性理解下:
每次kruskal algo都连接最大的不成环边
此时有2个未联通的联通块被连起来.
那么考虑u, v两点的联通块 : 它们并起来时选的边最大. (将比这条边大的边加入生成树不能使得u,v联通)
这个思想是kruskal重构树的基础(每个联通块选取一个代表点)

sb题, 但是做的噎屎了, 花了1.5h
我还是应该熟悉一下 最小生成树, 树上倍增和并查集
2个sb错误:

  1. 见code l58
  2. 并查集没初始化

    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

*/

猜你喜欢

转载自www.cnblogs.com/Eroad/p/9807818.html