Traffic Network in Numazu(LCA+树状数组)

这么激动的时刻当然要写一篇博客。

这道题在我找寻了重重bug以后终于AC了。

但是难以费解的是,我的样例都没有过就AC了。。。没错。各位大佬们如果看出哪里有问题还请指出,菜鸡实在不明白啊。

http://acm.hdu.edu.cn/showproblem.php?pid=6393

Problem Description

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.

Input

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.

Output

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.

Sample Input

 

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

Sample Output

5

6

6

6

Source

2018 Multi-University Training Contest 7

Recommend

chendu   |   We have carefully selected several similar problems for you:  6408 6407 6406 6405 6404 

这道题是一个n个点n条边的带有权值的一个图,然后1  是查询两点间的距离,0是修改操作

删掉环上的任意一条边后。进行比较操作。假设删掉的是X,Y这条边,我们要求的是u->v这条变得权值,就要考虑四种情况:

1.u到v

2.中间经过点X。u->X,X->v

3.中间经过点Y。

4.中间经过X和Y。但是先走x还是y还要再比较

然后lca模板的作用就是在中间求lca。

然后利用树状数组中的c,按照dfs序进行修改查询,logn的复杂度。

注意权值有关的要定为longlong。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=100005;
const int maxm=100005;
int cnt,num,head[maxn];
int first[maxn],que[maxn<<1];
int depth[maxn<<1];
int dp[maxn<<1][20];
int dist[maxn];
bool vis[maxn];
int last[maxn];///
LL w[maxn];///
int xpp[maxn];
LL C[maxn];
int L[maxn];
int n,m,dfs_clock;
struct node{
    int to,next,val,id;
}G[maxm<<1];
void init(){
    memset(head,-1,sizeof(head));
    memset(vis,false,sizeof(vis));
    memset(C,0,sizeof(C));
    cnt=0;
    num=0;
    dfs_clock=0;
}
void add(int a,int b,int c,int id){///id方便赋值
    G[++cnt].to=b;
    G[cnt].val=c;
    G[cnt].next=head[a];
    G[cnt].id=id;
    head[a]=cnt;
}
int dfs(int u,int deep){
    vis[u]=true;///表示是否访问过
    que[++num]=u;///num在此处相当于dfs_clock
    first[u]=num;///表示第一次走的编号
    L[u]=++dfs_clock;
    depth[num]=deep;
    for(int i=head[u];i!=-1;i=G[i].next){
            int v=G[i].to;
            int w=G[i].val;
        if(!vis[v]){
            xpp[G[i].id]=v;
            dist[v]=dist[u]+w;
            dfs(v,deep+1);
           /// que[++num]=u;
           /// depth[num]=deep;
        }
    }
    last[u]=dfs_clock;///为什么一定要用时间戳???
}
void ST(int n)
{
    for(int i=1;i<=n;i++)
        dp[i][0] = i;
    for(int j=1;(1<<j)<=n;j++){
        for(int i=1;i+(1<<j)-1<=n;i++){
            int a = dp[i][j-1] , b = dp[i+(1<<(j-1))][j-1];
            dp[i][j] = depth[a]<depth[b]?a:b;
        }
    }
}
//两个节点之间的路径深度最小的就是LCA
int RMQ(int l,int r)
{
    int k=0;
    while((1<<(k+1))<=r-l+1)
        k++;
    int a = dp[l][k], b = dp[r-(1<<k)+1][k]; //保存的是编号
    return depth[a]<depth[b]?a:b;
}
int LCA(int u ,int v)
{
    int x = first[u] , y = first[v];
    if(x > y) swap(x,y);
    int res = RMQ(x,y);
    return que[res];
}
int lowbit(int i){
    return i&(-i);
}
void update(int i,LL x)
{
    for(;i<=n;i+=lowbit(i))
        C[i]+=x;
}
LL sum(int i)
{
    LL s=0;
    for(;i>0;i-=lowbit(i)) s+=C[i];
    return s;
}

long long Dist(int u,int v)
{
  ///  cout<<"LCA:"<<LCA(u,v)<<endl;
  ///  cout<<"first[LCA]"<<L[LCA(u,v)]<<endl;
    return sum(L[u])+sum(L[v])-2*sum(L[LCA(u,v)]);
}

int main()
{
    int t,a,b,c,u,k,v,val;
    scanf("%d",&t);
    while(t--){
        init();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n-1;i++){
            scanf("%d%d%d",&a,&b,&c);
            add(a,b,c,i);
            add(b,a,c,i);
            w[i]=c;
        }
        dfs(1,1);
      ///  ST(2*n-1);
      ST(2*n-1);
       int X,Y,Z;
        scanf("%d%d%d",&X,&Y,&Z);
        w[n]=Z;
        for(int i=1;i<n;i++){
            update( L[ xpp[i] ],w[i]);
            update(last[xpp[i]]+1,-w[i]);
        }
        while(m--){
            scanf("%d",&k);
            if(k==0){
                scanf("%d%d",&a,&val);
                if(a==n)
                    w[a] = val;
                else{
                    update(L[xpp[a]],val-w[a]);
                    update(last[xpp[a]]+1,-val+w[a]);
                    w[a]=val;
                }
            }
            else{
                scanf("%d%d",&u,&v);
                long long ans=Dist(u,v);
               /// cout<<"1:"<<ans<<endl;
                ans=min(ans,Dist(u,X)+Dist(v,X));
              ///  cout<<"lala:"<<Dist(u,X)<<"  "<<Dist(v,X)<<endl;
              ///  cout<<"2:"<<ans<<endl;
                ans=min(ans,Dist(u,Y)+Dist(v,Y));
              ///  cout<<"3:"<<ans<<endl;
                ans=min(ans,Dist(u,X)+Dist(v,Y)+Z);
              ///  cout<<"4:"<<ans<<endl;
                ans=min(ans,Dist(u,Y)+Dist(v,X)+Z);
              ///  cout<<"5:"<<ans<<endl;
                printf("%lld\n",ans);
            }
        }
    }
    return 0;
}
/*
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
*/

代码:

猜你喜欢

转载自blog.csdn.net/xianpingping/article/details/81713514