【kruscal】【最小生成树】【块状树】bzoj3732 Network

跟去年NOIP某题基本一样。

最小生成树之后,就变成了询问连接两点的路径上的权值最大的边。

倍增LCA、链剖什么的随便搞。

块状树其实也是很简单的,只不过每个点的点权要记录成“连接其与其父节点的边的权值”,然后暴力LCA时不要用LCA的值更新答案了。

  1 #include<cmath>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 #define maxn 15001
  7 int Res,Num;char C,CH[20];
  8 inline int Ge()
  9 {
 10     Res=0;C=‘*‘;
 11     while(C<‘0‘||C>‘9‘)C=getchar();
 12     while(C>=‘0‘&&C<=‘9‘){Res=Res*10+(C-‘0‘);C=getchar();}
 13     return Res;
 14 }
 15 inline void P(int x)
 16 {
 17     Num=0;if(!x){putchar(‘0‘);puts("");return;}
 18     while(x>0)CH[++Num]=x%10,x/=10;
 19     while(Num)putchar(CH[Num--]+48);
 20     putchar(‘\n‘);
 21 }
 22 struct Edge{int u,v,w;void Read(){u=Ge();v=Ge();w=Ge();}};
 23 bool cmp(const Edge &a,const Edge &b){return a.w<b.w;}
 24 Edge edges[maxn<<1];
 25 struct Graph
 26 {
 27     int v[maxn<<1],first[maxn<<1],next[maxn<<1],w[maxn<<1],en;
 28     void AddEdge(const int &a,const int &b)
 29     {v[++en]=b;next[en]=first[a];first[a]=en;}
 30     void AddEdge(const int &a,const int &b,const int &c)
 31     {v[++en]=b;w[en]=c;next[en]=first[a];first[a]=en;}
 32 };
 33 Graph G[2];
 34 int fa[maxn],dep[maxn],top[maxn],siz[maxn],sz,maxv[maxn],W[maxn];
 35 int n,m,q,x,y;
 36 void makeblock(int cur)
 37 {
 38     for(int i=G[0].first[cur];i;i=G[0].next[i])
 39       if(G[0].v[i]!=fa[cur])
 40         {
 41           dep[G[0].v[i]]=dep[cur]+1;
 42           W[G[0].v[i]]=G[0].w[i];
 43           fa[G[0].v[i]]=cur;
 44           if(siz[top[cur]]<sz)
 45             {
 46               siz[top[cur]]++;
 47               top[G[0].v[i]]=top[cur];
 48               G[1].AddEdge(cur,G[0].v[i]);
 49             }
 50           makeblock(G[0].v[i]);
 51         }
 52 }
 53 int rank[maxn],father[maxn];
 54 void init(){for(int i=1;i<=n;i++) father[i]=i;}
 55 int findroot(int x)
 56 {
 57     if(father[x]==x) return x;
 58     int rt=findroot(father[x]);
 59     father[x]=rt;
 60     return rt;
 61 }
 62 void Union(int U,int V)
 63 {
 64     if(rank[U]<rank[V]) father[U]=V;
 65     else
 66       {
 67         father[V]=U;
 68         if(rank[U]==rank[V]) rank[U]++;
 69       }
 70 }
 71 void dfs(int cur,int Maxnow)
 72 {
 73     maxv[cur]=Maxnow;
 74     for(int i=G[1].first[cur];i;i=G[1].next[i])
 75       dfs(G[1].v[i],max(Maxnow,W[G[1].v[i]]));
 76 }
 77 int Query_max(int u,int v)
 78 {
 79     int res=-2147483647;
 80     while(u!=v)
 81       {
 82           if(top[u]==top[v])
 83             {
 84                 if(dep[u]<dep[v]) swap(u,v);
 85                 res=max(res,W[u]);
 86                 u=fa[u];
 87             }
 88           else
 89             {
 90                 if(dep[top[u]]<dep[top[v]]) swap(u,v);
 91                 res=max(res,maxv[u]);
 92                 u=fa[top[u]];
 93             }
 94       }
 95     return res;
 96 }
 97 int main()
 98 {
 99     n=Ge();m=Ge();q=Ge();
100     for(int i=1;i<=m;i++) edges[i].Read();
101     sort(edges+1,edges+m+1,cmp);
102     init();
103     int cnt=0;
104     for(int i=1;i<=m;i++)
105       {
106           int f1=findroot(edges[i].u),f2=findroot(edges[i].v);
107           if(f1!=f2)
108             {
109                 Union(f1,f2);
110                 G[0].AddEdge(edges[i].u,edges[i].v,edges[i].w);
111                 G[0].AddEdge(edges[i].v,edges[i].u,edges[i].w);
112                 cnt++;
113                 if(cnt==n-1) break;
114             }
115       }
116     sz=sqrt(n);
117     for(int i=1;i<=n;i++)
118       {
119           top[i]=i;
120           siz[i]=1;
121       }
122     makeblock(1);
123     for(int i=1;i<=n;i++) if(top[i]==i) dfs(i,W[i]);
124     for(int i=1;i<=q;i++) {x=Ge();y=Ge();P(Query_max(x,y));}
125     return 0;
126 }
时间: 2024-10-11 17:10:11

【kruscal】【最小生成树】【块状树】bzoj3732 Network的相关文章

【块状树】【博弈论】bzoj3729 Gty的游戏

块状树,每个块的根记录一下当前块内距块根为奇数距离的异或和和偶数距离的异或和,询问的时候讨论一下即可. 总的节点数可能超过50000. #include<cstdio> #include<cmath> using namespace std; #define N 100001 int n,m,L,a[N]; int en,v[N<<1],next[N<<1],first[N]; int e2,v2[N<<1],nex2[N<<1],f

【块状树】【树链剖分】【线段树】bzoj3531 [Sdoi2014]旅行

离线后以宗教为第一关键字,操作时间为第二关键字排序. <法一>块状树,线下ac,线上tle…… #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<queue> using namespace std; queue<int>q; int f,c; inline void R(int &x){ c=0;f=1;

BZOJ 1086 SCOI2005 王室联邦 块状树

题目大意:给定一棵树,要求将这棵树分成一些块,使每块大小在[B,3B]之间 <手把手教你块状树系列> - -终于搞懂这题怎么做了 - -去网上扒了个代码居然是错的 坑死我了 - -还好题解的思想是对的 朴素的分块方式是贪心 能加就加 这种方法存在着严重的效率问题 可以被菊花卡成O(n)块 因此我们可以为其它的块预留位置 如果一块大小刚好>=b 就将这坨东西分成一块 首先任选一点开始深搜 维护一个栈 每个点退出递归时压栈 自下至上进行合并 如果某棵子树深搜完之后栈内元素数>=b 就把

【块状树】【树链剖分】bzoj1036 [ZJOI2008]树的统计Count

很早之前用树链剖分写过,但是代码太长太难写,省选现场就写错了. 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 using namespace std; 5 #define lson rt<<1,l,m 6 #define rson rt<<1|1,m+1,r 7 #define maxn 60000 8 int n,m,u,v; 9 int V[maxn],Next[

【块状树】bzoj3731 Gty的超级妹子树

带 加点 删边的块状树. 加点在 bzoj3720 说过. 删边其实就是块顶打标记,记录其属于哪棵树,防止在dfs搜集答案时跑到别的树上. 然后暴力把所在块拆开. 好像用邻接表存图,直接在vector里删边也行? 1 #include<cstdio> 2 #include<algorithm> 3 #include<cmath> 4 #include<vector> 5 using namespace std; 6 #define maxn 200001 7

【最近公共祖先】【块状树】CODEVS 1036 商务旅行

在线块状树LCA模板. 1 #include<cstdio> 2 #include<vector> 3 #include<algorithm> 4 #include<cmath> 5 using namespace std; 6 #define N 30001 7 vector<int>G[N]; 8 typedef vector<int>::iterator ITER; 9 int dep[N],x,y,fa[N],top[N],s

bzoj3732: Network(最小生成树+LCA)

3732: Network 题目:传送门 题解: 第一眼就看到最大边最小,直接一波最小生成树. 一开始还担心会错,问了一波肉大佬,任意两点在最小生成树上的路径最大边一定是最小的. 那么事情就变得简单起来了嘿嘿嘿,建棵树,直接在线LCA啊,用一个mx[i][j]记录i往上2^j这段区间的最大值. 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5

BZOJ 1083: [SCOI2005]繁忙的都市【Kruscal最小生成树裸题】

1083: [SCOI2005]繁忙的都市 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 2925  Solved: 1927[Submit][Status][Discuss] Description 城市C是一个非常繁忙的大都市,城市中的道路十分的拥挤,于是市长决定对其中的道路进行改造.城市C的道 路是这样分布的:城市中有n个交叉路口,有些交叉路口之间有道路相连,两个交叉路口之间最多有一条道路相连 接.这些道路是双向的,且把所有的交叉路口直接或

【BZOJ-1086】王室联邦 分块 + 块状树

1086: [SCOI2005]王室联邦 Time Limit: 10 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1094  Solved: 650[Submit][Status][Discuss] Description “余”人国的国王想重新编制他的国家.他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理.他的国家有n个城市,编号为1..n.一些城市之间有道路相连,任意两个不同的城市之间有且仅有一条直接或间接的道路