zoukankan      html  css  js  c++  java
  • P1967 货车运输

    题面

    思路:最大生成树+树剖+线段树维护区间最小值。

    其中因为我们线段树维护边的信息很难搞我也不会qwq,所以我们把边权转化为点权。

    对于一条边的权值,我们把他下放到连接的两个点中深度大的点即儿子节点中,因为如果上放权值一个点可能对应好几条出边,而每个点入边只有一条。

    最后处理细节就好啦qwq。

    代码:

    #include <bits/stdc++.h>
    using namespace std;
    
    template<typename temp> void read(temp &x){
    	x = 0; temp f = 1; char ch;
    	while(!isdigit(ch = getchar())) (ch == '-') and (f = -1);
    	for(x = ch^48; isdigit(ch = getchar()); x = (x<<3)+(x<<1)+(ch^48));
    	x *= f;
    }
    template<typename temp, typename ...res> void read(temp &a, res& ...some){read(a), read(some...);}
    
    const int maxn = 1e5;
    
    int n, m, q, num, fa[maxn], a[maxn];
    pair<pair<int,int>, int> e[maxn];
    
    vector<pair<int,int> >v[maxn];
    vector<pair<pair<int,int>, int> >qwq;
    
    struct poutree{
    	#define ls (now << 1)
    	#define rs (now<<1|1)
    	#define mid ((l+r)>>1)
    	int cnt, fa[maxn], dep[maxn], height_son[maxn], top[maxn], dfn[maxn], id[maxn], size[maxn];
    	struct no{
    		int l, r, minnum;
    	}node[maxn<<2];
    	void build_poutree(int now){
    		size[now] = 1;
    		for(int i = 0; i < v[now].size(); i ++){
    			int to = v[now][i].first;
    			if(dep[to]) continue;
    			dep[to] = dep[fa[to] = now] + 1;
    			build_poutree(to);
    			size[now] += size[to];
    			if(size[to] > size[height_son[now]]) height_son[now] = to;
    		}
    	}
    	void dfs(int now, int topfa){
    		top[id[dfn[now]=++cnt]=now] = topfa;
    		if(height_son[now]) dfs(height_son[now],topfa);
    		for(int i = 0; i < v[now].size(); i ++){
    			int to = v[now][i].first;
    			if(fa[now] == to or to == height_son[now]) continue;
    			dfs(to,to);
    		}
    	}
    	inline void up(int now){return(void)(node[now].minnum = min(node[ls].minnum, node[rs].minnum));}
    	void build_segtree(int l, int r, int now){
    		node[now].l = l, node[now].r = r;
    		if(l == r) return(void)(node[now].minnum = a[l]);
    		build_segtree(l, mid, ls), build_segtree(mid+1, r, rs);
    		return up(now);
    	}
    	void quary(int l, int r, int now, int &ans){
    		if(node[now].l > r or node[now].r < l) return;
    		if(l <= node[now].l and node[now].r <= r) return(void)(ans = min(ans, node[now].minnum));
    		quary(l, r, ls, ans), quary(l, r, rs, ans);
    		return up(now);
    	}
    	int lca(int x, int y){
    		int tmp = 1<<30;
    		while(top[x] != top[y]){
    			if(dep[top[x]] < dep[top[y]]) swap(x,y);
    			quary(dfn[top[x]], dfn[x], 1, tmp);
    			x = fa[top[x]];
    		}
    		if(dep[x] < dep[y]) swap(x,y);
    		quary(dfn[height_son[y]], dfn[x], 1, tmp);//这里注意一下是height_son[y]不是y
    		return tmp;
    	}
    	void build(){
    		for(int i = 1; i <= n; i ++){
    			if(!size[i]) build_poutree(i*(dep[i]=1)), dfs(i,i);
    		}
    		for(int i = 1; i <= n; i ++) a[i] = 1<<29;
    		for(int i = 0; i < qwq.size(); i ++){
    			a[dfn[dep[qwq[i].first.first]<dep[qwq[i].first.second]?qwq[i].first.second:qwq[i].first.first]] = qwq[i].second;
                            //权值下放到深度低的点上
    		}
    		return build_segtree(1,n,1);
    	}
    }tree;
    
    inline void add_edge(int x, int y, int z){
    	v[x].push_back(make_pair(y,z));
    	v[y].push_back(make_pair(x,z));
    	return;
    } 
    inline int find(int x){
    	if(fa[x] == x) return x;
    	return fa[x] = find(fa[x]);
    }
    bool tmp(pair<pair<int,int>, int> a, pair<pair<int,int>, int> b){
    	return a.second > b.second;
    }
    
    signed main(){
    	read(n, m);
    	for(int i = 1, x, y, z; i <= m; i ++){
    		read(x,y,z);
    		e[i].first.first = x, e[i].first.second = y, e[i].second = z;
    	}
    	sort(e+1,e+m+1,tmp);
    	for(int i = 1; i <= n; i ++) fa[i] = i;
    	for(int i = 1; i <= m; i ++){
    		int fx = find(e[i].first.first), fy = find(e[i].first.second);
    		if(fx == fy) continue;
    		qwq.push_back(e[i]);
    		fa[fx] = fy;
    		add_edge(e[i].first.first, e[i].first.second, e[i].second);	
    	}//最大生成树
    	tree.build();//构树
    	read(q);
    	for(int x, y; q; q --){
    		read(x,y);
    		if(find(x) != find(y)){
    			printf("-1
    ");
    			continue;
    		}else printf("%d
    ", tree.lca(x,y));
    	}
    	return 0;
    }
    
  • 相关阅读:
    水晶报表参数字段在代码中赋值
    存储过程编写经验和优化措施
    积分与排名
    大话处理器
    抽象数学
    开普勒:天空的立法者
    Scalable Face Image Retrieval with IdentityBased Quantization and Multireference Reranking
    配色辞典
    图像识别顶级赛事
    Information Geometry
  • 原文地址:https://www.cnblogs.com/Vanyun/p/13393967.html
Copyright © 2011-2022 走看看