1. 程式人生 > >[Noip2015]運輸計劃

[Noip2015]運輸計劃

tin 描述 break scrip || pre ora turn names

Description

公元2044年,人類進入了宇宙紀元。

L國有n個星球,還有n-1條雙向航道,每條航道建立在兩個星球之間,這n-1條航道連通了L國的所有星球。

小P掌管一家物流公司,該公司有很多個運輸計劃,每個運輸計劃形如:有一艘物流飛船需要從ui號星球沿最快的宇航路徑飛行到vi號星球去。顯然,飛船駛過一條航道是需要時間的,對於航道j,任意飛船駛過它所花費的時間為tj,並且任意兩艘飛船之間不會產生任何幹擾。

為了鼓勵科技創新,L國國王同意小P的物流公司參與L國的航道建設,即允許小P把某一條航道改造成蟲洞,飛船駛過蟲洞不消耗時間。

在蟲洞的建設完成前小P的物流公司就預接了m個運輸計劃。在蟲洞建設完成後,這m個運輸計劃會同時

開始,所有飛船一起出發。當這m個運輸計劃都完成時,小P的物流公司的階段性工作就完成了。

如果小P可以自由選擇將哪一條航道改造成蟲洞,試求出小P的物流公司完成階段性工作所需要的最短時間是多少?

Input

第一行包括兩個正整數n、m,表示L國中星球的數量及小P公司預接的運輸計劃的數量,星球從1到n編號。
接下來n-1行描述航道的建設情況,其中第i行包含三個整數ai, bi和ti,表示第i條雙向航道修建在ai與bi兩個星球之間,任意飛船駛過它所花費的時間為ti。
接下來m行描述運輸計劃的情況,其中第j行包含兩個正整數uj和vj,表示第j個運輸計劃是從uj號星球飛往vj號星球。

Output

共1行,包含1個整數,表示小P的物流公司完成階段性工作所需要的最短時間。

Sample Input

6 3
1 2 3
1 6 4
3 1 7
4 3 6
3 5 5
3 6
2 5
4 5

Sample Output

11

HINT

樣例說明】
將第1條航道改造成蟲洞:則三個計劃耗時分別為:11、12、11,故需要花費的時間為12。
將第2條航道改造成蟲洞:則三個計劃耗時分別為:7、15、11,故需要花費的時間為15。
將第3條航道改造成蟲洞:則三個計劃耗時分別為:4、8、11,故需要花費的時間為11。
將第4條航道改造成蟲洞:則三個計劃耗時分別為:11、15、5,故需要花費的時間為15。
將第5條航道改造成蟲洞:則三個計劃耗時分別為:11、10、6,故需要花費的時間為11。
故將第3條或第5條航道改造成蟲洞均可使得完成階段性工作的耗時最短,需要花費的時間為11。

【數據規模與約定】

所有測試數據的範圍和特點如下表所示

技術分享

#include<bits/stdc++.h>
#define MAXN 300005
using namespace std;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}
    while(ch>=0&&ch<=9){x=x*10+ch-0;ch=getchar();}
    return x*f;
}
struct Node{int v,w;};
struct Edge
{
    int u,v,lca,s;
    bool operator <(const Edge &a)const{return s>a.s;}
}e[MAXN];
vector<Node>g[MAXN];
int deep[MAXN],p[MAXN][25],dis[MAXN],n,m,maxE,maxx,sum[MAXN];
inline void dfs(int u,int fa)
{
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].v;
        if(v==fa) continue;
        deep[v]=deep[u]+1;
        p[v][0]=u;
        dis[v]=dis[u]+g[u][i].w;
        dfs(v,u);
    }
}
void init()
{
    dfs(1,0);
    for(int j=1;j<=20;j++)
        for(int i=1;i<=n;i++)
            p[i][j]=p[p[i][j-1]][j-1];
}
inline int lca(int u,int v)
{
    if(deep[u]>deep[v]) swap(u,v);
    for(int i=20;i>=0;i--)
        if(deep[p[v][i]]>=deep[u]) v=p[v][i];
    if(u==v) return u;
    for(int i=20;i>=0;i--)
        if(p[u][i]!=p[v][i])
        {
            u=p[u][i];
            v=p[v][i];
        }
    return p[u][0];
}
inline void getsum(int u,int fa,int tot)
{
    for(int i=0;i<g[u].size();i++)
    {
        int v=g[u][i].v;
        if(v==fa) continue;
        getsum(v,u,tot);
        sum[u]+=sum[v];
        if(sum[v]==tot) maxx=max(maxx,g[u][i].w);
    }
}
inline bool check(int mid)
{
    if(e[1].s-mid>maxE) return 1;
    if(mid>=e[1].s) return 0;
    memset(sum,0,sizeof(sum));
    int tot=0;
    for(int i=1;i<=m;i++)
    {
        if(e[i].s<=mid) break;
        sum[e[i].u]+=1;
        sum[e[i].v]+=1;
        sum[e[i].lca]-=2;
        tot++;
    }
    maxx=0;
    getsum(1,0,tot);
    if(maxx>=e[1].s-mid) return 0;
    return 1;
}
int main()
{
    n=read(),m=read();
    for(int i=1,u,v,w;i<=n-1;i++)
    {
        u=read(),v=read(),w=read();
        g[u].push_back((Node){v,w});
        g[v].push_back((Node){u,w});
        maxE=max(maxE,w);
    }
    init();
    for(int i=1,u,v;i<=m;i++)
    {
        u=read(),v=read();
        int t=lca(u,v);
        e[i]=(Edge){u,v,t,dis[u]+dis[v]-2*dis[t]};
    }
    sort(e+1,e+m+1);
    int l=0,r=e[1].s,ans;
    while(l<=r)
    {
        int mid=(l+r)>>1;
        if(check(mid))l=mid+1;
        else 
        {
            ans=mid;
            r=mid-1;
        }
    }
    printf("%d",ans);
}

[Noip2015]運輸計劃