Traffic Network in Numazu

Traffic Network in Numazu

題目描述

Chika is elected mayor of Numazu. She needs to manage the traffic in this city. To manage the traffic is too hard for her. So she needs your help. You are given the map of the city —— an undirected connected weighted graph with N nodes and N edges, and you have to finish Q missions. Each mission consists of 3 integers OP, X and Y. When OP=0, you need to modify the weight of the Xth edge to Y. When OP=1, you need to calculate the length of the shortest path from node X to node Y.html

輸入

The first line contains a single integer T, the number of test cases. Each test case starts with a line containing two integers N and Q, the number of nodes (and edges) and the number of queries. (3≤N≤105)(1≤Q≤105) Each of the following N lines contain the description of the edges. The ith line represents the ith edge, which contains 3 space-separated integers ui, vi, and wi. This means that there is an undirected edge between nodes ui and vi, with a weight of wi. (1≤ui,vi≤N)(1≤wi≤105) Then Q lines follow, the ith line contains 3 integers OP, X and Y. The meaning has been described above.(0≤OP≤1)(1≤X≤105)(1≤Y≤105) It is guaranteed that the graph contains no self loops or multiple edges.node

輸出

For each test case, and for each mission whose OP=1, print one line containing one integer, the length of the shortest path between X and Y.c++

樣例輸入

2 5 5 1 2 3 2 3 5 2 4 5 2 5 1 4 3 3 0 1 5 1 3 2 1 5 4 0 5 4 1 5 1 5 3 1 2 3 1 3 2 3 4 4 4 5 5 2 5 5 0 1 3 0 4 1 1 1 4數組

樣例輸出

5 6 6 6oop


基環樹

N個點 可是有N條邊 因此必定成環
簡單地講就是樹上在加一條邊
處理上分爲樹的處理和環的處理ui

參考 https://www.cnblogs.com/cly-none/p/9314812.htmlthis

本題先用並查集維護,找到那個環,將環中的任意一條邊去掉 就成爲樹了。樹能夠用LCA+樹狀數組&樹上差分處理,環就直接特判就行了。三條路,一個是隻走樹,一個是走到X再到Y再到v,一個是走到Y再到X再到u。spa

LCA

求最近公共祖先的模板code

//+ DFS
void dfs(ll u,ll fa){//dfs建樹
    dep[u]=dep[fa]+1;
    f[u][0]=fa;//初始化每一個點的父節點
    L[u]=++dfs_clock;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        if(v!=fa){
            G[e[i].id]=v;
            dfs(v,u);
        }
    }
    R[u]=dfs_clock;
}
//+ 初始化
void rmq_init(int n)
{
    for(int j=1;j<=19;j++)
        for(int i=1;i<=n;i++)
           if(f[i][j-1]) f[i][j] = f[f[i][j-1]][j-1];
}
//+ lca&rmq
int lca(int u,int v)
{
    if(dep[u]<dep[v]) swap(u,v);//深度深的先處理
    for(int i=19;i>=0;i--){
        if(dep[u]>=dep[v]+(1<<i)){
            u = f[u][i];
        }
    }
    if(u==v){//跳到同一深度判斷是否完成
        return u;
    }
    for(int i=19;i>=0;i--){//一塊兒跳
        if(f[u][i]!=f[v][i]){
            u=f[u][i];
            v=f[v][i];
        }
    }
    return f[u][0];
}
時間戳

dfs_clock 顧名思義就是遍歷到該點的時間。
R[ ]記錄着訪問該點的時間點 L[ ]記錄着該點最深的子節點的時間點。這樣處理利於樹狀數組。htm

樹狀數組

修改時支持對該區間前綴和的修改

距離

前綴和已經維護好了 因此兩點最短距離就是兩點的前綴和的和減去2倍的父節點的前綴和

#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
typedef long long ll;
struct Edge{
    int v,next,id;
}e[maxn<<1];
int n,a[maxn],head[maxn],dep[maxn<<1],cnt,pos[maxn],dfs_seq[maxn<<1],dfn,f[maxn<<1][20];
int L[maxn],R[maxn],dfs_clock,G[maxn];
ll W[maxn],C[maxn];
inline void add(int u,int v,int id){
    cnt++;
    e[cnt].v=v;
    e[cnt].next=head[u];
    e[cnt].id=id;
    head[u]=cnt;
}
inline int lowbit(int x){return (x)&(-x);}
void init(){
    memset(head,0,sizeof(head));
    memset(C,0,sizeof(C));
    memset(dep,0,sizeof(dep));
    cnt=0;
    dfs_clock=0;
}
void dfs(ll u,ll fa){//dfs建樹
    dep[u]=dep[fa]+1;
    f[u][0]=fa;//初始化每一個點的父節點
    L[u]=++dfs_clock;
    for(int i=head[u];i;i=e[i].next){
        int v=e[i].v;
        if(v!=fa){
            G[e[i].id]=v;
            dfs(v,u);
        }
    }
    R[u]=dfs_clock;
}
void rmq_init(int n)
{
    for(int j=1;j<=19;j++)
        for(int i=1;i<=n;i++)
           if(f[i][j-1]) f[i][j] = f[f[i][j-1]][j-1];
}
int lca(int u,int v)
{
    if(dep[u]<dep[v]) swap(u,v);//深度深的先處理
    for(int i=19;i>=0;i--){
        if(dep[u]>=dep[v]+(1<<i)){
            u = f[u][i];
        }
    }
    if(u==v){//跳到同一深度判斷是否完成
        return u;
    }
    for(int i=19;i>=0;i--){//一塊兒跳
        if(f[u][i]!=f[v][i]){
            u=f[u][i];
            v=f[v][i];
        }
    }
    return f[u][0];
}
inline void update(int i,ll x)
{
    for(;i<=n;i+=lowbit(i)) C[i]+=x;
}
inline ll sum(int i)
{
    ll s=0;
    for(;i>0;i-=lowbit(i)) s+=C[i];
    return s;
}
inline ll dist(int u,int v)
{
    return sum(L[u])+sum(L[v])-2*sum(L[lca(u,v)]);
}
int main()
{
    int i,u,v,k,q,T;
    ll w;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&q);
        init();
        for(i=1;i<=n-1;++i){
            scanf("%d%d%lld",&u,&v,&w);
            add(u,v,i);
            add(v,u,i);
            W[i]=w;
        }
        dfs(1,0);
        rmq_init(n);
        int X,Y; ll Z;
        scanf("%d%d%lld",&X,&Y,&Z);
        W[n] = Z;
        for(i=1;i<n;++i){
            update(L[G[i]],W[i]);
            update(R[G[i]]+1,-W[i]);
        }
        while(q--){
            scanf("%d",&k);
            if(k==0){
                scanf("%d%lld",&u,&w);
                if(u==n)
                    W[n] = w;
                else{
                    update(L[G[u]],w-W[u]);
                    update(R[G[u]]+1,-w+W[u]);
                    W[u]=w;
                }
            }
            else{
                scanf("%d%d",&u,&v);
                ll ans=dist(u,v);
                ans=min(ans,dist(u,X)+dist(v,Y)+Z);
                ans=min(ans,dist(u,Y)+dist(v,X)+Z);
                printf("%lld\n",ans);
            }
        }
    }
    return 0;
}
相關文章
相關標籤/搜索