杭电多校第七场 Traffic Network in Numazu


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

分析

比赛的时候傻了,,把树换成基环树就不会搞了。

  • 先把环中的任意一条边去除,边连接的两点记为r1,r2
  • 每次查询的时候,x与y之间的距离有三个:(1)去除边后树上的最短距离;(2)x->r1->r2->y;(3) x->r2->r1->y。取三个值中的最小值即可

代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
#include <map>
#include <cassert>
#include <cmath>
#include <vector>
using namespace std;
typedef long long ll;
const int maxn=100050;
int fa[maxn];
int find(int x) {
    return x==fa[x]?x:(fa[x]=find(fa[x]));
}
struct Edge {
    int v,nxt,d;
}e[maxn*2];
int h[maxn],tot,n,q;
void addEdge(int x,int y,int d) {
    e[++tot]=(Edge){y,h[x],d};
    h[x]=tot;
}
ll sum[maxn];
void add(int x,int val) {
    assert(x>0);
    while(x<=n) {
        sum[x]+=val;
        x+=(x&-x);
    }
}
ll query(int x) {
    ll ans=0;
    while(x) {
        ans+=sum[x];
        x-=(x&-x);
    }
    return ans;
}

int f[maxn][20],idx[maxn],cnt,dep[maxn],R[maxn];
void dfs(int x,int par,int val) {
    fa[x]=f[x][0]=par;
    dep[x]=dep[par]+1;
    idx[x]=++cnt;
    add(cnt,val);
    for(int i = 1; f[x][i-1]; ++i) f[x][i]=f[f[x][i-1]][i-1];
    for(int i = h[x]; i ; i=e[i].nxt) {
        if(par!=e[i].v) dfs(e[i].v,x,e[i].d);
    }
    R[x]=cnt;
    add(cnt+1,-val);
}
int lca(int x,int y) {
    if(dep[x]<dep[y]) swap(x,y);
    int h=dep[x]-dep[y];
    for(int i = 19; i >= 0; --i) {
        if(h&(1<<i)) x=f[x][i];
    }
    if(x==y) return x;
    for(int i = 19; i >= 0; --i) {
        if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    }
    return f[x][0];
}
ll dis(int x,int y) {
    int z=lca(x,y);
    return query(idx[x])+query(idx[y])-query(idx[z])*2;
}
int X[maxn],Y[maxn],W[maxn];
int main() {
    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%d%d", &n,&q);
        for(int i = 0; i <= n; ++i) h[i]=0,fa[i]=i,sum[i]=0;
        cnt=0,tot=0;
        int r1=0,r2=0,bw=0,ID;
        for(int i = 1; i <= n; ++i) {
            int x,y,w;
            scanf("%d%d%d", &x,&y,&w);
            if(find(x)==find(y)) {
                r1=x,r2=y,bw=w,ID=i;
            }
            else addEdge(x,y,w),addEdge(y,x,w),fa[find(x)]=find(y);
            X[i]=x,Y[i]=y,W[i]=w;
        }
        dfs(1,0,0);
        while(q--) {
            int op,x,y;
            scanf("%d%d%d", &op,&x,&y);
            if(op==0) {
                if(ID==x) bw=y;
                else {
                    int u=(fa[X[x]]==Y[x]?X[x]:Y[x]);
                    add(idx[u],-W[x]+y);
                    add(R[u]+1,W[x]-y);
                    W[x]=y;
                }
            }
            else {
                ll ans=dis(x,y);
                ans=min(ans,dis(r1,x)+dis(r2,y)+bw);
                ans=min(ans,dis(r1,y)+dis(r2,x)+bw);
                printf("%lld\n", ans);
            }
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/sciorz/p/9473558.html

时间: 2024-07-28 21:19:16

杭电多校第七场 Traffic Network in Numazu的相关文章

2019杭电多校第七场 HDU - 6656 Kejin Player——概率&amp;&amp;期望

题意 总共有 $n$ 层楼,在第 $i$ 层花费 $a_i$ 的代价,有 $pi$ 的概率到 $i+1$ 层,否则到 $x_i$($x_i \leq 1$) 层.接下来有 $q$ 次询问,每次询问 $l$ 层到 $j$ 层的期望代价. 分析 这种期望具有可加性,因此,维护一个前缀和 $sum[i]$:从 $1$ 到 $i$ 的期望. 设从 $i$ 到 $i+1$ 的期望代价为 $E$,则有 $E = a_i + (1-\frac{r_i}{s_i})(sum[i]-sum[x_i]+E)$ 解得

2019 杭电多校 第七场

2019 Multi-University Training Contest 7 补题链接:2019 Multi-University Training Contest 7 1001 A + B = C 题意: 给出 \(a, b, c\),求 \(x, y, z\) 满足 \(a\cdot 10^x + b\cdot 10^y = c\cdot 10^z\).\(a, b, c \le 10^{100000}\). 题解: 补零到 \(a, b, c\) 长度相等之后,可能的情况只有四种: \

HDU 5742 It&#39;s All In The Mind (贪心) 2016杭电多校联合第二场

题目:传送门. 题意:求题目中的公式的最大值,且满足题目中的三个条件. 题解:前两个数越大越好. #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; int gcd(int a,int b) { if(!b) return a; return gcd(b,a%b); } int main() { int t; ci

2019 杭电多校 第五场

2019 Multi-University Training Contest 5 补题链接:2019 Multi-University Training Contest 5 罚时爆炸 自闭场 1004 equation (HDU 6627) 题意: 给定一个整数 \(C\) 和 \(N\) 组 \(a_i,b_i\),求 \(∑_{i=1}^N|a_i\cdot x + b_i| = C\) 的所有解,如果有无穷多个解就输出 -1. 思路 分类讨论 分类讨论去绝对值.根据 \(b_i / a_i

[补]2019HDU杭电多校第五场H

红小豆又被奇怪的东西卡住了 参考于:思路https://www.cnblogs.com/st1vdy/p/11309280.html 样例https://www.cnblogs.com/dd-bond/p/11308155.html HDU-6631 line symmetric 多边形轴对称类问题.关于多边形轴对称目前可以公开的情报可见第一篇blog的大佬画的图,主要就是奇偶问题.本题主要思路是枚举实现找轴和验证对称,注意判自交的方式. 初步认识可以做一下hdu3902. 在下还是专注于讲心路

HDU 5745 La Vie en rose (DP||模拟) 2016杭电多校联合第二场

题目:传送门. 这是一道阅读理解题,正解是DP,实际上模拟就能做.pij+1 指的是 (pij)+1不是 pi(j+1),判断能否交换输出即可. #include <iostream> #include <algorithm> #include <cstdio> #include<cstring> using namespace std; int t,n; char str1[100009],str2[5009]; char tmp[5009]; int m

HDU 5734 Acperience (公式推导) 2016杭电多校联合第二场

题目:传送门. #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; int gcd(long long a,long long b) { if(!b) return a; return gcd(b,a%b); } int a[100005]; int main() { int T,n; scanf("%d

HDU 5744 Keep On Movin (贪心) 2016杭电多校联合第二场

题目:传送门. 如果每个字符出现次数都是偶数, 那么答案显然就是所有数的和. 对于奇数部分, 显然需要把其他字符均匀分配给这写奇数字符. 随便计算下就好了. #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; int main() { int T,n,a; scanf("%d",&T);

杭电多校第三场 A Ascending Rating

Problem Description Before the start of contest, there are n ICPC contestants waiting in a long queue. They are labeled by 1 to n from left to right. It can be easily found that the i-th contestant's QodeForces rating is ai.Little Q, the coach of Qua