HDU 3078:Network(LCA之tarjan)

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

题意:给出n个点n-1条边m个询问,每个点有个权值,询问中有k,u,v,当k = 0的情况是将u的权值修改成v,当k不为0的情况是问u和v的路径中权值第k大的点的权值是多少。

思路:比较暴力的方法,可能数据太水勉强混过去了。对于每一个询问的时候保留两个点之间的lca,还有计算出两个点之间的点的个数(询问的时候如果点的个数小于k就不用算了),然后tarjan算完之后对每个询问再暴力路径上的每个点放进vector排序输出第k大..

  1 #include <cstdio>
  2 #include <cstring>
  3 #include <algorithm>
  4 #include <iostream>
  5 #include <queue>
  6 #include <cmath>
  7 #include <map>
  8 #include <vector>
  9 using namespace std;
 10 #define N 80010
 11 #define M 30010
 12 struct node
 13 {
 14     int u, v, next;
 15 }edge[N*2];
 16 struct P
 17 {
 18     int u, v, next, num, k, lca;
 19 }Edge[M*2];
 20 int n, m, tot, Tot, head[N], Head[N], a[N], fa[N], dis[N];
 21 bool vis[N];
 22 vector<int> vec;
 23
 24 void init()
 25 {
 26     tot = Tot = 0;
 27     memset(head, -1, sizeof(head));
 28     memset(Head, -1, sizeof(Head));
 29     memset(dis, -1, sizeof(dis));
 30     memset(vis, false, sizeof(vis));
 31     for(int i = 1; i <= n; i++) fa[i] = i;
 32 }
 33
 34 void add(int u, int v)
 35 {
 36     edge[tot].u = u; edge[tot].v = v; edge[tot].next = head[u]; head[u] = tot++;
 37 }
 38
 39 void Add(int u, int v, int k)
 40 {
 41     Edge[Tot].k = k; Edge[Tot].u = u; Edge[Tot].v = v; Edge[Tot].next = Head[u]; Edge[Tot].num = 0; Edge[Tot].lca = -1; Head[u] = Tot++;
 42 }
 43
 44 int Find(int x)
 45 {
 46     while(x != fa[x]) x = fa[x];
 47     return x;
 48 }
 49
 50 void Merge(int u, int v)
 51 {
 52     u = Find(u), v = Find(v);
 53     fa[v] = u;
 54 }
 55
 56 void tarjan(int u)
 57 {
 58     vis[u] = true;
 59     for(int i = head[u]; ~i; i = edge[i].next) {
 60         int v = edge[i].v;
 61         if(!vis[v]) {
 62             dis[v] = dis[u] + 1;
 63             tarjan(v);
 64             fa[v] = u;
 65         }
 66     }
 67     for(int i = Head[u]; ~i; i = Edge[i].next) {
 68         int v = Edge[i].v, k = Edge[i].k;
 69         if(vis[v]) {
 70             int ff = Find(v);
 71             if(k) {
 72                 Edge[i].num = Edge[i^1].num = dis[u] + dis[v] - 2 * dis[ff];
 73                 Edge[i].lca = Edge[i^1].lca = ff;
 74             }
 75             else a[u] = v;
 76         }
 77     }
 78 }
 79
 80 int doit(int u, int v, int k, int num, int lca)
 81 {
 82     vec.clear();
 83     while(u != lca) {
 84         vec.push_back(a[u]); u = fa[u];
 85     }
 86     while(v != lca) {
 87         vec.push_back(a[v]); v = fa[v];
 88     }
 89     vec.push_back(a[lca]);
 90     sort(vec.begin(), vec.end());
 91     num++;
 92     return vec[num-k];
 93 }
 94
 95 void solve()
 96 {
 97     for(int i = 0; i < Tot; i += 2) {
 98         int u = Edge[i].u, v = Edge[i].v, k = Edge[i].k, num = Edge[i].num, lca = Edge[i].lca;
 99         if(k) {
100             if(num + 1 < k) puts("invalid request!");
101             else printf("%d\n", doit(u, v, k, num, lca));
102         }
103     }
104 }
105
106 int main()
107 {
108     scanf("%d%d", &n, &m);
109     init();
110     for(int i = 1; i <= n; i++) scanf("%d", a+i);
111     for(int i = 1; i < n; i++) {
112         int u, v;
113         scanf("%d%d", &u, &v);
114         add(u, v); add(v, u);
115     }
116     for(int i = 0; i < m; i++) {
117         int u, v, k;
118         scanf("%d%d%d", &k, &u, &v);
119         Add(u, v, k); Add(v, u, k);
120     }
121     dis[1] = 0;
122     tarjan(1);
123     solve();
124     return 0;
125 }
时间: 2024-07-30 20:30:31

HDU 3078:Network(LCA之tarjan)的相关文章

HDU 3078 Network LCA水题

Problem Description The ALPC company is now working on his own network system, which is connecting all N ALPC department. To economize on spending, the backbone network has only one router for each department, and N-1 optical fiber in total to connec

hdu 3078 Network lca

题目链接 给一棵树, m个操作, 一共两种操作, 将第x个点的权值改为y, 询问x->y路径上权值第k大的点的权值. 暴力的找..... 1 #include <iostream> 2 #include <vector> 3 #include <cstdio> 4 #include <cstring> 5 #include <algorithm> 6 #include <cmath> 7 #include <map>

HDU - 3078 Network(暴力+LCA)

题目大意:给出n个点的权值,m条边,2种操作 0 u num,将第u个点的权值改成num k u v,询问u到v这条路上第k大的权值点 解题思路:该点的话直接该,找第k大的话直接暴力 #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define N 80010 #define M 160010 struct Edge{ int to, next, val; }

HDU 2460 Network 傻逼Tarjan

Network Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1014    Accepted Submission(s): 206 Problem Description A network administrator manages a large network. The network consists of N comput

HDU 3078 Network

Network Problem Description The ALPC company is now working on his own network system, which is connecting all N ALPC department. To economize on spending, the backbone network has only one router for each department, and N-1 optical fiber in total t

HDU 4738 Caocao&#39;s Bridges tarjan求桥

Caocao's Bridges Problem Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. But he wouldn't give up. Caocao's army still was not good at water battles, so he came up with another idea. He built many islands in the Chan

hdu 4738 Caocao&#39;s Bridges tarjan

Caocao's Bridges Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=4738 Description Caocao was defeated by Zhuge Liang and Zhou Yu in the battle of Chibi. But he wouldn't give up. Caocao's army still was not good

HDU 2460 Network(双连通+树链剖分+线段树)

HDU 2460 Network 题目链接 题意:给定一个无向图,问每次增加一条边,问个图中还剩多少桥 思路:先双连通缩点,然后形成一棵树,每次增加一条边,相当于询问这两点路径上有多少条边,这个用树链剖分+线段树处理 代码: #include <cstdio> #include <cstring> #include <algorithm> #include <vector> using namespace std; #pragma comment(linke

hdu 1269 迷宫城堡 (tarjan算法学习)

迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 7056    Accepted Submission(s): 3137 Problem Description 为了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单向的,就是说若称某通道连通了A

LCA (Tarjan&amp;倍增)

LCA_Tarjan 参考博客:https://www.cnblogs.com/JVxie/p/4854719.html LCA的Tarjan写法需要结合并查集 从叶子节点往上并 int Find (int x) { return x == pre[x] ? x:pre[x] = Find(pre[x]); } void dfs(int x,int w,int fa) { d[x] = w; //点x的深度 //遍历与点x相连的点(除了已经访问过的和其父节点) for (int i = 0; i