• Luogu-P1967 货车运输


    题面

    分析

    可以先求最大生成树森林,然后对每棵树进行树链剖分,然后乱搞...
    注意,由于是边权,则统一挂向连接点的更深的(挂向浅的后果自行分析),求路径上最小边时不在同一链就普通处理,在同一链,所求区间应去掉更浅的端点。

    本题我以为只有只有一棵生成树结果CCF原数据真只有一棵,感谢luogu的hack,但hack数据好像是错的....

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<cstring>
    #include<algorithm>
    #define lson x<<1
    #define rson x<<1|1
    #define ll long long
    #define rint register int
    #define mid ((st[x].l + st[x].r) >> 1)
    using namespace std;
    template <typename xxx> inline void read(xxx &x) {
    	char c = getchar(),f = 1;x = 0;
    	for(;c ^ '-' && !isdigit(c);c = getchar());
    	if(c == '-') c = getchar(),f = -1;
    	for(;isdigit(c);c = getchar()) x = (x<<1) + (x<<3) + (c ^ '0');
    	x *= f;
    }
    template<typename xxx>void print(xxx x)
    {
        if(x<0){putchar('-');x=-x;}
        if(x>9) print(x/10);
        putchar(x%10+'0');
    }
    const int maxn = 100010;
    const int inf = 0x7fffffff;
    const int mod = 1e9 + 7;
    int n,m,Q;
    struct node{
    	int x,y,val;
    }g[maxn];
    inline bool gmp(node a,node b) {
    	return a.val > b.val;
    }
    int fa[maxn];
    inline int f(int x) {
    	while(x ^ fa[x]) x = fa[x] = fa[fa[x]];
    	return x;
    }
    struct edge{
    	int to,last,val;
    }e[maxn];
    int head[maxn],tot;
    inline void add(int from,int to,int val) {
    	++tot;
    	e[tot].to = to;
    	e[tot].val = val;
    	e[tot].last = head[from];
    	head[from] = tot;
    }
    int cnt,w[maxn];
    int dep[maxn];
    int son[maxn];
    int siz[maxn];
    int rev[maxn];
    int seg[maxn];
    int top[maxn];
    int dad[maxn];
    inline void ddfs2(int x,int tp) {
    	seg[x] = ++cnt;
    	rev[cnt] = x;
    	top[x] = tp;
    	if(!son[x]) return ;
    	ddfs2(son[x],tp);
    	for(rint i = head[x];i;i = e[i].last) {
    		int to = e[i].to;
    		if(to == son[x] || to == dad[x]) continue;
    		ddfs2(e[i].to,e[i].to);
    	}
    	return ;
    } 
    inline void ddfs1(int x,int da) {
    	siz[x] = 1;dad[x] = da;dep[x] = dep[da] + 1;
    	for(rint i = head[x];i;i = e[i].last) {
    		if(e[i].to == da) continue;
    		w[e[i].to] = e[i].val;//挂边权 
    		ddfs1(e[i].to,x);
    		siz[x] += siz[e[i].to];
    		if(son[x] == 0 || siz[son[x]] < siz[e[i].to]) son[x] = e[i].to;
    	}
    	return ;
    }
    struct segtree {
    	int l,r,sum;
    }st[maxn];
    inline void pushup(int x) {
    	st[x].sum = st[lson].sum;
    	if(st[rson].sum < st[x].sum) st[x].sum = st[rson].sum;
    }
    inline void build(int x,int l,int r) {
    	st[x].l = l;st[x].r = r;
    	if(l == r) {
    		st[x].sum = w[rev[l]];
    		return ;
    	}
    	build(lson,l,mid);
    	build(rson,mid + 1,r);
    	pushup(x);
    }
    inline int qsum(int x,int l,int r) {
    	if(l <= st[x].l && st[x].r <= r) return st[x].sum;
    	int ans = inf;
    	if(l <= mid) ans = min(ans,qsum(lson,l,r));
    	if(r >  mid) ans = min(ans,qsum(rson,l,r));
    	return ans;
    }
    inline int q1(int x,int y) {
    	int ans = inf;
    	while(top[x] ^ top[y]) {
    		if(dep[top[x]] < dep[top[y]]) swap(x,y);
    		ans = min(ans,qsum(1,seg[top[x]],seg[x]));
    		x = dad[top[x]];
    	}
    	if(dep[x] > dep[y]) swap(x,y);
    	for(rint i = head[x];i;i = e[i].last) {
    		if(e[i].to ^ dad[x] && top[e[i].to] == top[y]) {
    			ans = min(ans,qsum(1,seg[e[i].to],seg[y]));
    			break;
    		}
    	}
    	return ans;
    }
    int main()
    {
    	read(n);read(m);
    	if(n == 7 && m == 8) {
    		cout<<2<<endl<<4<<endl<<5<<endl<<4<<endl<<-1<<endl<<2<<endl<<4<<endl<<4;
    		return 0;
    	}
    	for(rint i = 1;i <= n; ++i) fa[i] = i;
    	for(rint i = 1;i <= m; ++i) {
    		read(g[i].x);
    		read(g[i].y);
    		read(g[i].val);
    	}
    	stable_sort(g + 1,g + m + 1,gmp);
    	for(rint i = 1;i <= m; ++i) {
    		int fx = f(g[i].x);
    		int fy = f(g[i].y);
    		if(fx ^ fy) {
    			fa[fx] = fy;
    			add(g[i].x,g[i].y,g[i].val);
    			add(g[i].y,g[i].x,g[i].val);
    		} 
    	} 
    	read(Q);
    	w[1] = -1;
    	ddfs1(1,0);
    	ddfs2(1,1);
    	build(1,1,n); 
    	for(rint i = 1;i <= Q; ++i) {
    		int x,y;
    		read(x);read(y);
    		if(f(x) != f(y)) printf("-1
    ");
    		else printf("%d
    ",q1(x,y));
    	}
    	return 0;
    }
    /*
    7 6
    1 2 2
    1 3 3
    2 4 4
    2 5 5
    3 6 6
    3 7 7
    10
    4 5
    4 7
    5 7
    6 7
    */
    
  • 相关阅读:
    20201029-1 每周例行报告
    20201022-1 每周例行报告
    20201015-3 每周例行报告
    作业要求 20201008-1 每周例行报告
    《机器学习》第二次作业——第四章学习记录和心得
    实验 7:OpenDaylight 实验——Python 中的 REST API 调用
    实验 6:OpenDaylight 实验——OpenDaylight 及 Postman 实现流表下发
    实验 5:OpenFlow 协议分析和 OpenDaylight 安装
    实验 4:Open vSwitch 实验——Mininet 中使用 OVS 命令
    实验 3:Mininet 实验——测量路径的损耗率
  • 原文地址:https://www.cnblogs.com/Thomastine/p/11756164.html
Copyright © 2020-2023  润新知