zoukankan      html  css  js  c++  java
  • BZOJ 3732 Network 最小瓶颈路

    题目大意:给出一个无向边,非常多询问,问x,y两地之间的最长路最短是多少。


    思路:乍一看好像是二分啊。

    的确这个题二分能够做。可是时间会慢非常多,有的题直接就T掉(NOIP2013货车运输)。

    事实上这个题的模型就是最小瓶颈路模型。

    解法就是把无向图变成一个最小生成树,然后两点之间的最长路就是满足题意的答案。


    CODE:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define MAX 15010
    #define INF 0x7f7f7f7f
    using namespace std;
    
    struct Complex{
    	int x,y,len;
    
    	bool operator <(const Complex &a)const {
    		return len < a.len;
    	}
    	void Read() {
    		scanf("%d%d%d",&x,&y,&len);
    	}
    }edge[MAX << 2];
    
    int points,edges,asks;
    int head[MAX],total;
    int next[MAX << 1],length[MAX << 1],aim[MAX << 1];
    
    int fa[MAX];
    
    int deep[MAX];
    int father[MAX][20],min_length[MAX][20];
    
    void Pretreatment();
    int Find(int x);
    
    inline void Add(int x,int y,int len);
    
    void DFS(int x,int last);
    void SparseTable();
    
    int GetLCA(int x,int y);
    
    int main()
    {
    	cin >> points >> edges >> asks;
    	Pretreatment();
    	for(int i = 1;i <= edges; ++i)
    		edge[i].Read();
    	sort(edge + 1,edge + edges + 1);
    	for(int i = 1;i <= edges; ++i) {
    		int fx = Find(edge[i].x);
    		int fy = Find(edge[i].y);
    		if(fx != fy) {
    			Add(edge[i].x,edge[i].y,edge[i].len);
    			Add(edge[i].y,edge[i].x,edge[i].len);
    			fa[fx] = fy;
    		}
    	}
    	DFS(1,0);
    	SparseTable();
    	for(int x,y,i = 1;i <= asks; ++i) {
    		scanf("%d%d",&x,&y);
    		printf("%d
    ",GetLCA(x,y));
    	}
    	return 0;
    }
    
    void Pretreatment()
    {
    	for(int i = 1;i <= points; ++i)
    		fa[i] = i;
    }
    
    int Find(int x)
    {
    	if(fa[x] == x)	return x;
    	return fa[x] = Find(fa[x]);
    }
    
    inline void Add(int x,int y,int len)
    {
    	next[++total] = head[x];
    	aim[total] = y;
    	length[total] = len;
    	head[x] = total; 
    }
    
    void DFS(int x,int last)
    {
    	deep[x] = deep[last] + 1;
    	for(int i = head[x];i;i = next[i]) {
    		if(aim[i] == last)	continue;
    		father[aim[i]][0] = x;
    		min_length[aim[i]][0] = length[i];
    		DFS(aim[i],x);
    	}
    }
    
    void SparseTable()
    {
    	for(int j = 1;j < 20; ++j)
    		for(int i = 1;i <= points; ++i) {
    			father[i][j] = father[father[i][j - 1]][j - 1];
    			min_length[i][j] = max(min_length[i][j - 1],min_length[father[i][j - 1]][j - 1]);
    		}
    }
    
    int GetLCA(int x,int y)
    {
    	int re = 0;
    	if(deep[x] < deep[y])	swap(x,y);
    	for(int i = 19;i >= 0; --i)
    		if(deep[father[x][i]] >= deep[y]) {
    			re = max(re,min_length[x][i]);
    			x = father[x][i];
    		}
    	if(x == y)	return re;
    	for(int i = 19;i >= 0; --i)
    		if(father[x][i] != father[y][i]) {
    			re = max(re,min_length[x][i]);
    			re = max(re,min_length[y][i]);
    			x = father[x][i];
    			y = father[y][i];
    		}
    	re = max(re,min_length[x][0]);
    	re = max(re,min_length[y][0]);
    	return re;
    }


  • 相关阅读:
    C++ mutex&&RWlock
    一个资源池模型
    C++安全编码摘录
    C++点滴
    git常用命令(转)
    ASN.1
    TDOA泰勒级数法
    teamviewer解除最大通话限制-特别破解版(转)
    剑指offer——旋转数组的最小数字
    常见的相关分析方法——结合实例
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/6800033.html
Copyright © 2011-2022 走看看