【题】【树(最大生成树&LCA)】NKOJ 2495 货车运输 【NOIP2013-D1T3】

6 篇文章 0 订阅
4 篇文章 0 订阅

NKOJ 2495 货车运输 【NOIP2013-D1T3】
时间限制 : 10000 MS 空间限制 : 128000 KB

问题描述
A国有n座城市,编号从1到n,城市之间有m条双向道路。
每一条道路对车辆都有重量限制,简称限重。
现在有q辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。

输入格式
第一行有两个用一个空格隔开的整数 n,m,表示 A 国有n座城市和m条道路。
接下来m行,每行3个整数x,y,z,表示从x号城市到y号城市有一条限重为z的道路(x≠y,两座城市之间可能有多条道路)
接下来一行有一个整数 q,表示有 q 辆货车需要运货。
接下来q行,每行两个整数x,y,之间用一个空格隔开,表示一辆货车需要从x城市运输货物到y城市(x≠y)。

输出格式
输出共有 q 行,每行一个整数,表示对于这一辆货车,它的最大载重是多少。
如果货车不能到达目的地,输出-1。

样例输入
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3

样例输出
3
-1
3

提示
对于 30%的数据,1<=n<=1000,1<=m<=10000,1<=q<=1000;
对于 60%的数据,1<=n<=1000,1<=m<=50000,1<=q<=1000;
对于 100%的数据,1<=n<=10000,1<=m<=50000,1<=q<=30000,0<=z<=100000。

思路:
重边处理:最大生成树
森林处理:并查集
对于每次询问,并查集查询是否在一颗树上,不在输出-1,在,则LCA。

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const double log_2=log(2);
const int inf=1e9;
const int needn=10003;
const int needm=50003;

struct fy{int a,b,val;}w[needm];

int s=0,m=0;
int belong[needn],dep[needn],fa[needn][17],val[needn][17];
int la[needn*2],len[needn*2],en[needn*2],fi[needn];
bool visit[needn],use[needn]; 
//...................................................................
inline void in_(int &d)
{
    bool mark=false;char t=getchar();
    while(t<'0'||t>'9'){if(t=='-') mark=true;t=getchar();}
    for(d=0;t>='0'&&t<='9';t=getchar())d=(d<<3)+(d<<1)-'0'+t;
    if(mark)d=-d;
}  
char o[100];
inline void out_(int x)
{   
    int l=1;
    if(x<0) x=-x,putchar('-');  
    if(!x) putchar('0');  
    for(;x;x/=10) o[l++]=x%10+'0';  
    for(l--;l;l--)putchar(o[l]);  
    putchar('\n');  
}  
//...................................................................
void add(int a,int b,int c)
{
    m++;
    en[m]=b;
    len[m]=c;
    la[m]=fi[a];
    fi[a]=m;
}
//...................................................................
int getbelong(int x)
{
    return x==belong[x]?x:belong[x]=getbelong(belong[x]);
}
//...................................................................
bool way(fy x,fy y)
{
    return x.val>y.val;
}
//...................................................................
void dfs(int x)
{
    int k=ceil(log(dep[x])/log_2);
    s=max(s,k);
    for(int i=1;i<=k;i++)
    {
        fa[x][i]=fa[fa[x][i-1]][i-1];
        val[x][i]=min(val[x][i-1],val[fa[x][i-1]][i-1]);
    } 
    int t=fi[x],y;
    while(t)
    {
        y=en[t];
        if(visit[y])
        {
            t=la[t];
            continue ;
        }
        fa[y][0]=x;
        dep[y]=dep[x]+1;
        val[y][0]=len[t];
        visit[y]=true;
        dfs(y);
        t=la[t];
    }
}
//...................................................................
/*void go_up(int &v,int p)
{
    for(int i=0;i<=s;i++) if(p&(1<<i)) v=fa[v][i];
}*/ 
int lca(int u,int v)
{
    if(dep[u]>dep[v]) swap(u,v);
    //go_up(v,dep[v]-dep[u]);
    int p=dep[v]-dep[u],ans=1e9;
    for(int i=0;i<=s;i++) if((p>>i)&1) ans=min(ans,val[v][i]),v=fa[v][i];
    if(v==u) return ans;
    for(int i=s;i>=0;i--) if(fa[v][i]!=fa[u][i]) ans=min(ans,min(val[v][i],val[u][i])),v=fa[v][i],u=fa[u][i];
    return min(ans,min(val[v][0],val[u][0]));
} 
/*int getmin(int v,int u)//u 在 v上方 
{
    int p=dep[v]-dep[u],ans=inf;
    for(int i=0;i<=s;i++) 
     if(p&(1<<i)) 
     {
        ans=min(ans,val[v][i]);
        v=fa[v][i];
     }
    return ans;
}*/ 
//...................................................................
int main()
{
    //freopen("a.txt","r",stdin);
    int n,m;in_(n),in_(m);//scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) belong[i]=i;
    for(int i=1;i<=m;i++) in_(w[i].a),in_(w[i].b),in_(w[i].val);//scanf("%d%d%d",&w[i].a,&w[i].b,&w[i].val);
    //...................................................................
    sort(w+1,w+1+m,way);
    int x,y;
    for(int i=1;i<=m;i++)
    {
        x=getbelong(w[i].a),y=getbelong(w[i].b);
        if(x!=y)
        {
            belong[x]=y;
            add(w[i].a,w[i].b,w[i].val),add(w[i].b,w[i].a,w[i].val);
        }
    }
    //...................................................................
    for(int i=1;i<=n;i++) 
     if(!use[getbelong(i)]) 
     {
        visit[i]=true;
        dfs(i);
        use[getbelong(i)]=true;
     } 
    //................................................................... 
    int q;in_(q);//scanf("%d",&q);
    for(int i=1,a,b;i<=q;i++)
    {
        in_(x),in_(y);//scanf("%d%d",&x,&y);
        if(getbelong(x)!=getbelong(y)) puts("-1");
        else 
        {
            out_(lca(x,y));
            //a=getmin(x,c),b=getmin(y,c);
            //out_(min(a,b));//printf("%d\n",min(a,b));
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值