zoukankan      html  css  js  c++  java
  • 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
    ", 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
    ", 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
    
    */
    
  • 相关阅读:
    SQL Server CHARINDEX和PATINDEX详解
    MVC ListBoxFor raises “value cannot be null” exception
    jquery.uploadify动态传递表单元素
    C# 判断一字符串是否为合法数字(正则表达式)
    jquery 操作Listbox
    JQuery 操作 ListBox间移动和ListBox内移动
    jQuery获取Select选择的Text和 Value
    SQL 语句的执行效率
    JSON 序列化长度限制问题
    C#中利用FileSystemWatcher对单个文件内容的监视
  • 原文地址:https://www.cnblogs.com/Eroad/p/9807818.html
Copyright © 2011-2022 走看看