zoukankan      html  css  js  c++  java
  • ICPC Latin American Regional 2017-Imperial roads(LCA)

    Description

    The roads of Cubiconia are in a dire state, after years of neglect and lack of maintenance. Each road
    connects two different cities A and B and can be traveled in both ways (from A to B or from B to A). There is at most one road between each pair of cities, and using the existing roads it is possible to travel between any pair of cities. The new emperor of Cubiconia has just raised the taxes (again!), but promised to repair at least some of the roads, guaranteeing that Cubiconians will be able to travel between any pair of cities using only restored roads. The Department of Public Works have calculated the cost of repairing each individual road. Now they want to calculate the minimum cost for repairing a set of roads so that the emperor’s promise is made true. This is not easy because the emperor wants the set of repaired roads to include one particular road, but he has not yet decided which particular road to include: could be the one that connects the city where his castle is to the city where his daughter’s royal residence is, or the road that connects the city where his summer palace is to the only city by the seaside, or. . . Fearing the emperor will take too long to decide, the engineers want your help. Given the description of the roads in Cubiconia, with their respective repairing costs, you must write a program to answer a set of queries. For each query you will be given one specific road that should be repaired, and must determine the minimum cost for repairing a set of roads (including the given specific road) so that Cubiconians will be able to travel between any pair of cities using only restored roads.

    Input

    The first line contains two integers N (2 ≤ N ≤ 105) and R (N − 1 ≤ R ≤ 2 × 105), representing respectively the number of cities and the number of roads in Cubiconia. Cities are identified by distinct integers from 1 to N. Each of the next R lines describes a road with three integers A, B (1 ≤ A < B ≤ N) and C (1 ≤ C ≤ 104 ), indicating that there is a road between cities A and B and the cost of repairing it is C. There is at most one road between each pair of cities, and using the existing roads it is
    possible to travel between any pair of cities. The next line contains an integer Q (1 ≤ Q ≤ 105) representing the number of queries. Each of the next Q lines describes a query with two integers U and V (1 ≤ U < V ≤ N), indicating the specific road that should be repaired. There are no repeated queries.

    Output

    Output Q lines, each line with an integer indicating the answer to the corresponding query of the input, that is, the minimum cost for repairing a set of roads (including the specific road in the query) so that Cubiconians will be able to travel between any pair of cities using only restored roads.

    样例输入

    样例输入1:

    3 3
    1 2 10
    2 3 5
    1 3 7
    3
    2 3
    1 2
    1 3
    

    样例输出1:

    12
    15
    12
    

    样例输入2:

    4 4
    1 2 1
    2 4 1
    2 3 100
    1 4 50
    1
    1 4
    

    样例输出2:

    151
    

    样例输入3:

    5 7
    1 2 8
    1 3 10
    2 4 5
    2 3 12
    4 5 4
    3 5 14
    1 5 20
    3
    2 3
    1 5
    3 5
    

    样例输出3:

    29
    39
    31
    

    题目大意:
    给出n个点,m条边的一个图,q个询问,
    每次询问给出两个点u,v,问包含u-v这条边的最小生成树是多少

    这道题比较板
    首先求一下这个图的最小生成树对于这n个点,最小生成树一定是n-1条边,如果说再加上一条边,一定会构成一个环。
    我们把生成的这个最小生成树看作是一个以1为根节点的最小生成树。
    所以说在下面的q个询问中,如果说这条边用到了最小生成树中(这条边是最小生成树上的边),那么直接输出当前最小生成树的代价就好;如果说当前这条边没有出现在最小生成树当中,那么最小生成树的权值val加上这条边之后就构成了一个环,求出这两个点所在的环内的最大边权,并将这个边权减去,就是最终结果
    那么如何求这两个点之间的最大边权呢?
    看下面这张图;
    在这里插入图片描述
    假如这就是我们求得的最小生成树(默认根为1),然后我们要求出包含10号节点到11号节点这条边的最小生成树:
    先把10-11这条边加进去,很显然构成了4-5-7-8-10-11-6-4这样的一个环,为了要求得最小生成树,那么我们就要将这个环里面的最大边权得边给去掉,重点是我们如何找到这个边。
    显然dfs一定会T飞,我们将这个环去掉10-11之后的状态看作是一个以4为根节点的树4更好就是这两个点的LCA,再求lca的过程中,我们就可以记录下最大值。用上倍增之后,复杂度是说的过去的。找到这个最大边权之后再减去就是最终答案。

    Code:

    int head[maxn],cnt;
    struct node {
    	int u,v,nex;
    	ll w;
    	friend bool operator <(node a,node b) {
    		return a.w < b.w;
    	}
    } a[maxn],e[maxn];
    void add(int u,int v,ll w){
    	e[cnt].u = u;
    	e[cnt].v = v;
    	e[cnt].w = w;
    	e[cnt].nex = head[u];
    	head[u] = cnt ++;
    }
    int n,m,q;
    int fa[maxn];
    int maxi[maxn][30];
    int beiz[maxn][30];
    int depth[maxn];
    void dfs(int u,int fa) {
    	//beiz[u][0] = fa;
    	for(int i=head[u]; ~i; i=e[i].nex) {
    		int to = e[i].v;
    		if(to == fa) continue;
    		depth[to] = depth[u] + 1;
    		beiz[to][0] = u;
    		maxi[to][0] = e[i].w;
    		for(int d=1; d<=19; d++) {
    			beiz[to][d] = beiz[beiz[to][d-1]][d-1];
    			maxi[to][d] = max(maxi[to][d-1],maxi[beiz[to][d-1]][d-1]);
    		}
    		dfs(to,u);
    	}
    }
    int lca(int x,int y) {
    	int ret = 0;
    	if(depth[x] < depth[y]) swap(x,y);
    	for(int i=19; i>=0; i--) {
    		if(depth[beiz[x][i]] >= depth[y]) {
    			ret = max(ret,maxi[x][i]);
    			x = beiz[x][i];
    		}
    	}
    	if(x == y) return ret;
    	for(int i=19; i>=0; i--) {
    		if(beiz[x][i] != beiz[y][i]) {
    			int mx = max(maxi[x][i],maxi[y][i]);
    			ret = max(ret,mx);
    			x = beiz[x][i];
    			y = beiz[y][i];
    		}
    	}
    	return ret= max(ret,max(maxi[x][0],maxi[y][0]));
    	///return ret = Max(ret,maxi[x][0],maxi[y][0]);
    }
    int findFa(int x){
    	if(x == fa[x]) return x;
    	else return fa[x] = findFa(fa[x]);
    }
    typedef pair<int,int> PII;
    map<PII,bool> kru;
    map<PII,ll>wight;
    int main() {
    	cin >> n >> m;
    	for(int i=1; i<=m; i++) {
    		a[i].u=read,a[i].v=read,a[i].w=read;
    		wight[{a[i].u,a[i].v}] = a[i].w;
    		wight[{a[i].v,a[i].u}] = a[i].w;
    	}
    	memset(head,-1,sizeof head);
    	sort(a+1,a+1+m);
    	ll val = 0LL;
    	for(int i=0;i<maxn;i++) fa[i] = i; 
    	for(int i=1;i<=m;i++){
    		int u = a[i].u;
    		int v = a[i].v;
    		int fau = findFa(u);
    		int fav = findFa(v);
    		if(fau == fav) continue;
    		fa[fau] = fav;
    		val += a[i].w;
    		kru[{u,v}] = 1,kru[{v,u}] = 1;
    		add(u,v,a[i].w),add(v,u,a[i].w);
    	}
    	depth[1] = 0;
    	dfs(1,0); // 0 is the father of 1
    	cin >> q;
    	while(q --){
    		int u=read,v=read;
    		if(kru[{u,v}]) cout << val <<endl;
    		else{
    			int t = lca(u,v);
    			// cout << t <<endl;
    			cout << val + wight[{u,v}] - t<<endl;
    		}
    	}
    	return 0;
    }
    /*
    
    */
    
  • 相关阅读:
    oracle聚合函数及行专列,pivot rollup cube
    oracle expdp导入时 提示“ORA-39002: 操作无效 ORA-39070: 无法打开日志文件 ”
    PL/SQL 美化器不能解析文本
    PL/SQL TOAD 不安装Oracle客户端连接数据库的方法
    oracle 某一字段取反
    jqgrid 加按钮列
    扩展方法 DataTable的ToList<T>
    jquery ajax调用WCF,采用System.ServiceModel.WebHttpBinding
    jquery ajax调用WCF,采用System.ServiceModel.WSHttpBinding协议
    学习WCF笔记之二
  • 原文地址:https://www.cnblogs.com/PushyTao/p/15101051.html
Copyright © 2011-2022 走看看