码迷,mamicode.com
首页 > 其他好文 > 详细

Luogu-P1967 货车运输

时间:2019-10-29 00:03:29      阅读:86      评论:0      收藏:0      [点我收藏+]

标签:dad   生成   sort   pre   code   最小   print   template   ++i   

题面

分析

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

本题我以为只有只有一棵生成树结果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\n");
        else printf("%d\n",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
*/

Luogu-P1967 货车运输

标签:dad   生成   sort   pre   code   最小   print   template   ++i   

原文地址:https://www.cnblogs.com/Thomastine/p/11756164.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!