HDU 5452 Minimum Cut 树链剖分 + LCA
来源:互联网 发布:淘宝商品资质要填吗 编辑:程序博客网 时间:2024/05/22 14:18
大致题意:N-1条边形成一棵树;接下来M-N+1条边(u,v)表示从u走到v经过的所有边边权+1。这似乎是裸的树链剖分,但是我裸的树链剖分TLE了,M-N+1条边,这个常数还是很大的,我的树链剖分插入复杂度是log(N)*log(N),所以大概的复杂度是M*log(N)*log(N),是在这里超时了,可以想到(1,u)和v到(1,v)经过的边都+1,然后(1,LCA(u,v))经过的边-2,发现处理出来的边都是以1开头,就可以减少插入边的条数了。
Code:
#include <map>#include <set>#include <queue>#include <cmath>#include <cstdio>#include <cstring>#include <cstdlib>#include <iostream>#include <algorithm>using namespace std;const int MAXN = 25000;struct Edge { int to ; Edge * next;}E[MAXN*2],*EE;struct Gragh { Edge * first;}G[MAXN];struct Tree { int x,y; int value; int lazy;}t[MAXN<<2];int pre[MAXN],son[MAXN],siz[MAXN],dep[MAXN],top[MAXN],pos[MAXN],Rank[MAXN];int N,M,K;int num[MAXN];int tree_idx = 0;int tot ;void Init() { EE = E; dep[1] = 1; pre[1] = 0; tree_idx = 0; tot = 1; memset(G,0,sizeof(G)); memset(num,0,sizeof(num));}void addedge(int u,int v) { EE->to = v ; EE->next = G[u].first ; G[u].first = EE++; EE->to = u ; EE->next = G[v].first ; G[v].first = EE++;}void dfs1(int u) { siz[u] = 1; son[u] = 0; for(Edge * p = G[u].first ; p ; p = p -> next) { if(p->to != pre[u]) { pre[p->to] = u; dep[p->to] = dep[u] + 1; dfs1(p->to); siz[u] += siz[p->to]; if(siz[p->to] > siz[son[u]]) son[u] = p -> to; } }}void dfs2(int u,int ancestor) { top[u] = ancestor; tree_idx ++; pos[u] = tree_idx; if(son[u] != 0) { dfs2(son[u],ancestor); } for(Edge * p = G[u].first ; p ; p = p -> next) { if(p->to != pre[u] && p->to != son[u]) { dfs2(p->to,p->to); } }} void Push_Up(int rt) { t[rt].value = min(t[rt<<1].value,t[rt<<1|1].value); }void Push_Down(int rt) { if(t[rt].lazy) { t[rt<<1].lazy += t[rt].lazy; t[rt<<1|1].lazy += t[rt].lazy; t[rt<<1].value += t[rt].lazy; t[rt<<1|1].value += t[rt].lazy; t[rt].lazy = 0; }}void Build(int x,int y,int rt) { t[rt].x = x ; t[rt].y = y; t[rt].lazy = 0; if(x == y) { t[rt].value = 1; if(x == 1) t[rt].value = 0x3f3f3f3f; return ; } int mid = (x + y) >> 1; Build(x,mid,rt<<1); Build(mid+1,y,rt<<1|1); Push_Up(rt);}void Update(int rt,int left,int right,int lazy) { if(t[rt].x >= left && t[rt].y <= right) { t[rt].lazy += lazy; t[rt].value += lazy; return ; } int mid = (t[rt].x + t[rt].y) >> 1; Push_Down(rt); if(mid >= left) { Update(rt<<1,left,right,lazy); } if(mid < right) { Update(rt<<1|1,left,right,lazy); } Push_Up(rt);}int ans;// void Query(int rt,int left,int right) {// if(t[rt].x == t[rt].y) {// ans = min(t[rt].value,ans);// return ;// }// int mid = (t[rt].x + t[rt].y) >> 1;// Push_Down(rt);// if(mid >= left) {// Query(rt<<1,left,right);// } // if(mid < right) {// Query(rt<<1|1,left,right);// }// // Push_Up(rt);// }void Change(int x,int y,int lazy) { //printf("lazy : %d\n",lazy); while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x,y); Update(1,pos[top[x]],pos[x],lazy); x = pre[top[x]]; } if(x == y) return ;//如果是更新路径上的点,去掉这一句; if(dep[x] > dep[y]) swap(x,y); Update(1,pos[x]+1,pos[y],lazy);//如果是更新路径上的点,去掉+1}// void Query_Tree(int x,int y) {// while(top[x] != top[y]) {// if(dep[top[x]] < dep[top[y]]) swap(x,y);// Query(1,pos[top[x]],pos[x]);// x = pre[top[x]];// }// if(x == y) return ;// if(dep[x] > dep[y]) swap(x,y);// Query(1,pos[x]+1,pos[y]);// }int lca(int x,int y) { while(top[x] != top[y]) { if(dep[top[x]] < dep[top[y]]) swap(x,y); x = pre[top[x]]; } if(x == y) return x; if(dep[x] > dep[y]) swap(x,y); return x;}char op[5];// void print_tree(int rt) {// //printf("x : %d y : %d lazy : %d\n",t[rt].x,t[rt].y,t[rt].lazy);// if(t[rt].x == t[rt].y) {// printf("value : %d lazy : %d\n",t[rt].value,t[rt].lazy);// return ;// }// print_tree(rt<<1);// print_tree(rt<<1|1);// }int ReadInt() { char c = getchar(); while(c > '9' || c < '0') c = getchar(); int ret = 0; while(c <= '9' && c >= '0') { ret = ret * 10 + c - '0'; c = getchar(); } return ret;}void input() { scanf("%d %d",&N,&M); int u,v; for(int i = 1 ; i <= N - 1; i++) { scanf("%d %d",&u,&v); // u = ReadInt(); // v = ReadInt(); addedge(u,v); } dfs1(1); dfs2(1,1); Build(1,N,1); for(int i = 1 ; i <= M - N + 1; i++) { scanf("%d %d",&u,&v); num[u] ++; num[v] ++; int temp = lca(u,v); // printf("temp : %d\n",temp); num[temp] -= 2; // u = ReadInt(); // v = ReadInt(); } for(int i = 1 ; i <= N ; i++) { if(num[i]) { Change(1,i,num[i]); } } ans = 0x3f3f3f3f; //print_tree(1); // Query(1,2,N); //Query_Tree(2,N); //print_tree(1); printf("%d\n",t[1].value);}int main(void) { //freopen("a.in","r",stdin); int T,casenum=1; scanf("%d",&T); while(T--){ printf("Case #%d: ",casenum++); Init(); input(); //solve(); } return 0;}
0 0
- HDU 5452 Minimum Cut 树链剖分 + LCA
- 【LCA】HDU 5452Minimum Cut
- hdu 5452 Minimum Cut (LCA)
- HDU 5452 Minimum Cut(LCA+DFS)
- Minimum Cut (hdu 5452 离线LCA)
- hdoj 5452 Minimum Cut 【LCA or 树链剖分】
- HDU 5452 Minimum Cut(LCA+树形DP)
- hdu 5452 Minimum Cut(树链剖分)
- HDU 5452 Minimum Cut
- hdu 5452 Minimum Cut
- hdu 5452 Minimum Cut
- HDU 5452-C - Minimum Cut 树链剖分
- HDU 5452 Minimum Cut(LCA & RMQ & DFS)——2015 ACM/ICPC Asia Regional Shenyang Online
- HDU 5452 Minimum Cut 2015沈阳网络赛(在线LCA)
- hdu 5452 Minimum Cut(树链剖分+差分前缀和)
- [HDU 5452] Minimum Cut (树链剖分+树状数组)
- HDU 5631Minimum Cut-Cut
- HDU 5452 Minimum Cut(贪心)
- git的基本用法_随记
- 频谱分析相关知识
- uva 1045 - The Great Wall Game(二分图匹配)
- 【SCOI2011】糖果 差分约束
- 【mysql学习系列】Mysql数据库导入官方示例数据库
- HDU 5452 Minimum Cut 树链剖分 + LCA
- 杭电acm--2047
- HDOJ 1715 大菲波数 (大数相加)
- Codeforces round #321 (DIV. 2)
- (php)form&文件上传
- 今目标的反思
- 面试---const与#define的区别
- 对语言的评估!!
- 由今目标想开来