【noip2013提高組day1T3】 貨車運輸 RMQ+LCA+倍增+最大生成樹

P1967 貨車運輸

數據範圍
題目描述

A 國有 n 座城市,編號從 1 到 n,城市之間有 m 條雙向道路。每一條道路對車輛都有重量限制,簡稱限重。現在有 q 輛貨車在運輸貨物, 司機們想知道每輛車在不超過車輛限重的情況下,最多能運多重的貨物。

輸入輸出格式

輸入格式:
輸入文件名爲 truck.in。

輸入文件第一行有兩個用一個空格隔開的整數 n,m,表示 A 國有 n 座城市和 m 條道

路。 接下來 m 行每行 3 個整數 x、 y、 z,每兩個整數之間用一個空格隔開,表示從 x 號城市到 y 號城市有一條限重爲 z 的道路。意:x 不等於 y,兩座城市之間可能有多條道路。

接下來一行有一個整數 q,表示有 q 輛貨車需要運貨。

接下來 q 行,每行兩個整數 x、y,之間用一個空格隔開,表示一輛貨車需要從 x 城市運輸貨物到 y 城市,注意:x 不等於 y。

輸出格式:
輸出文件名爲 truck.out。

輸出共有 q 行,每行一個整數,表示對於每一輛貨車,它的最大載重是多少。如果貨

車不能到達目的地,輸出-1。

輸入輸出樣例

輸入樣例#1:
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
輸出樣例#1:
3
-1
3
說明

對於 30%的數據,0 < n < 1,000,0 < m < 10,000,0 < q< 1,000; 對於 60%的數據,0 < n < 1,000,0 < m < 50,000,0 < q< 1,000; 對於 100%的數據,0 < n < 10,000,0 < m < 50,000,0 < q< 30,000,0 ≤ z ≤ 100,000。

這裏寫圖片描述

注意:
1.注意維護limit數組和f數組的時候的順序
2.可以加入另一個並查集數組判斷-1的情況,優化。
3.求最大生成樹注意有重邊的情況,所以先進行一遍從大到小的排序,先加入的邊一定是最優的。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100006
#define inf 2147483647
using namespace std;
int e_num,n,m;
int head[N*2];
int father[N],mother[N];
int deep[N],vis[N];
struct node1
{
    int x,y,v;
}love[N];
struct node2
{
    int to,dis,next;
}e[N*2];
struct node3
{
    int c,fa;
}f[N*2][20];
int get()
{
    int x=0,p=1;char c;
    c=getchar();
    while (c<'0'||c>'9') {if (c=='-') p=-1;c=getchar();}
    while (c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
    return x*p;
}
void add(int from,int to,int dis)
{
    ++e_num;
    e[e_num].to=to;
    e[e_num].dis=dis;
    e[e_num].next=head[from];
    head[from]=e_num;
}
bool cmp(node1 a,node1 b)
{
    return a.v>b.v;
}
int find_father(int x)
{
    if (father[x]!=x) father[x]=find_father(father[x]);
    return father[x];
}
void mix_father(int x,int y)
{
    int xx,yy;
    xx=find_father(x);
    yy=find_father(y);
    father[yy]=xx;
}
int find_mother(int x)
{
    if (mother[x]!=x) mother[x]=find_mother(mother[x]);
    return mother[x];
}
void mix_mother(int x,int y)
{
    int xx,yy;
    xx=find_mother(x);
    yy=find_mother(y);
    mother[yy]=xx;
}
void rmq(int t)
{
    int i;
    for (i=1;i<=20;i++)
    {
        if (deep[t]<(1<<i))
            break;
        f[t][i].c=min(f[f[t][i-1].fa][i-1].c,f[t][i-1].c);
        f[t][i].fa=f[f[t][i-1].fa][i-1].fa; 
    }
    vis[t]=true;
    for (i=head[t];i;i=e[i].next)
        if (!vis[e[i].to])
        {
            deep[e[i].to]=deep[t]+1;
            f[e[i].to][0].fa=t;
            f[e[i].to][0].c=e[i].dis;
            rmq(e[i].to);
        }
}
void kruskal()
{
    int i,k=0;
    for (i=1;i<=m;i++)
    {
        if (find_father(love[i].x)==find_father(love[i].y))
           continue;
        mix_father(love[i].x,love[i].y);
        k++;
        add(love[i].x,love[i].y,love[i].v);
        add(love[i].y,love[i].x,love[i].v);
        if (k==n-1) break;
    }
}
int lca(int x,int y)
{
    int i,ans=inf;
    if (deep[x]<deep[y])
    {
        swap(x,y);
    }
    for (i=20;i>=0;i--)
    {
        if (deep[x]-deep[y]>=(1<<i))
        {
            ans=min(f[x][i].c,ans);
            x=f[x][i].fa;   
        }    
    }
    if (x==y) return ans;
    int u=0;
    while (deep[x]>=(1<<u)) u++;
    for (i=u;i>=0;i--)
        if (f[x][i].fa!=f[y][i].fa)
        {
            ans=min(f[x][i].c,ans);
            x=f[x][i].fa;
            ans=min(f[y][i].c,ans);
            y=f[y][i].fa;
        }
    return min(ans,min(f[x][0].c,f[y][0].c));
}
int main()
{
    int x,y,i;
    scanf("%d%d",&n,&m);
    for (i=1;i<=n;i++) mother[i]=i;
    for (i=1;i<=m;i++)
    {
        love[i].x=get();love[i].y=get();love[i].v=get();
        mix_mother(love[i].x,love[i].y);
    }
    sort(love+1,love+m+1,cmp);
    for (i=1;i<=n;i++) father[i]=i;
    kruskal();
    rmq(1);
    int q=get();
    for (i=1;i<=q;i++)
    {
        x=get();y=get();
        if (find_mother(x)!=find_mother(y)) {printf("-1\n");continue;}
        printf("%d\n",lca(x,y));
    }
} 
發佈了79 篇原創文章 · 獲贊 32 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章