zoukankan      html  css  js  c++  java
  • bzoj3732-Network

    题意

    给出一个 (n) 个点 (m) 条边的无向图,(q) 次询问 ((x,y)) 的所有路径中最长边最小是多少。

    (n,m,qle 3 imes 10^4)

    分析

    题意明显是最小生成树上两点之间最大边权。有三种做法。当模板题玩一玩就好了。

    第一种是简单的最小生成树上倍增,复杂度为 (O(nlog n))

    第二种是最小生成树上用lct求最大边权,复杂度为 (O(nlog n))

    第三种是kruskal重构树上倍增lca,复杂度为 (O(nlog n))

    代码

    这是第三种做法。

    #include<bits/stdc++.h>
    using namespace std;
    inline char nchar() {
    	static const int bufl=1<<20;
    	static char buf[bufl],*a,*b;
    	return a==b && (b=(a=buf)+fread(buf,1,bufl,stdin),a==b)?EOF:*a++;
    }
    inline int read() {
    	int x=0,f=1;
    	char c=nchar();
    	for (;!isdigit(c);c=nchar()) if (c=='-') f=-1;
    	for (;isdigit(c);c=nchar()) x=x*10+c-'0';
    	return x*f;
    }
    const int maxn=3e4+1;
    const int maxm=3e4+1;
    const int maxj=15;
    int n,m,q,tot;
    struct edge {
    	int x,y,w;
    	inline bool operator < (const edge &a) const {return w<a.w;}
    } e[maxm];
    int f[maxn];
    int find(int x) {return f[x]==x?x:f[x]=find(f[x]);}
    namespace tree {
    	vector<int> g[maxn];
    	int w[maxn],f[maxn][maxj],dep[maxn];
    	inline void add(int x,int y) {g[x].push_back(y);}
    	void dfs(int x,int fa) {
    		dep[x]=dep[fa]+1;
    		f[x][0]=fa;
    		for (int j=1;j<maxj;++j) f[x][j]=f[f[x][j-1]][j-1];
    		for (vector<int>::iterator it=g[x].begin();it!=g[x].end();++it) dfs(*it,x);
    	}
    	inline int lca(int x,int y) {
    		if (dep[x]<dep[y]) swap(x,y);
    		for (int j=maxj-1;j>=0;--j) if (dep[f[x][j]]>=dep[y]) x=f[x][j];
    		if (x==y) return x;
    		for (int j=maxj-1;j>=0;--j) if (f[x][j]!=f[y][j]) x=f[x][j],y=f[y][j];
    		return f[x][0];
    	}
    }
    int main() {
    #ifndef ONLINE_JUDGE
    	freopen("test.in","r",stdin);
    #endif
    	tot=n=read(),m=read(),q=read();
    	for (int i=1;i<=m;++i) {
    		int x=read(),y=read(),w=read();
    		e[i]=(edge){x,y,w};
    	}
    	for (int i=1;i<(n<<1);++i) f[i]=i;
    	sort(e+1,e+m+1);
    	for (int i=1;i<=m;++i) {
    		int &x=e[i].x,&y=e[i].y,&w=e[i].w;
    		int fx=find(x),fy=find(y);
    		if (fx!=fy) {
    			f[fx]=f[fy]=++tot;
    			tree::w[tot]=w;
    			tree::add(tot,fx),tree::add(tot,fy);
    		}
    	}
    	tree::dfs(tot,tot);
    	while (q--) {
    		int x=read(),y=read();
    		int ans=tree::w[tree::lca(x,y)];
    		printf("%d
    ",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    关键词user附近有语法错误
    Java期末考试冲刺总结
    getElementsByName&getElementById
    window.location.herf传值问题
    三种提示框
    statement没有返回结果集问题
    ajax从jsp向servlet传值
    java.sql.SQLException: Access denied for user ''@'localhost' (using password: NO)报错问题解决
    Unregistering application product with eureka with status DOWN
    输出废弃
  • 原文地址:https://www.cnblogs.com/owenyu/p/7295668.html
Copyright © 2011-2022 走看看