[51NOD1743][JZOJ4899]雪之国度
来源:互联网 发布:网站备案域名怎么买 编辑:程序博客网 时间:2024/05/02 03:28
题目大意
给定
有
题目分析
考虑一种最暴力的做法,按边权从小到大插入边,动态维护边双连通分量。连通分量内的答案可以瞎处理。然而这样很难维护。
怎么办呢?用最小生成树来维护一个联通性,这样然后在树上可以更方便的处理边双内路径的最大权值。我们可能会加入某些边使得它有环,那么环内权值就要变成加入这条边的权值(加入边肯定更大)。但是修改过一次的边我们就不能再修改了,因为显然它达到了条件且不会更优。因此我们使用并查集来将所有修改过的点并在一起,这样修改时就可以暴力沿着并查集父亲修改了。
处理询问的话,倍增查询路径最大值即可。
时间复杂度
代码实现
#include <algorithm>#include <iostream>#include <cstdio>#include <cctype>#include <cmath>using namespace std;int read(){ int x=0,f=1; char ch=getchar(); while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar(); while (isdigit(ch)) x=x*10+ch-'0',ch=getchar(); return x*f;}int buf[30];void write(int x){ if (x<0) x=-x,putchar('-'); for (;x;x/=10) buf[++buf[0]]=x%10; if (!buf[0]) buf[++buf[0]]=0; for (;buf[0];) putchar('0'+buf[buf[0]--]);}const int N=100050;const int M=500050;const int E=N<<1;const int LGN=17;struct edge{ int x,y,l;}e[M];bool operator<(edge a,edge b){return a.l<b.l;}int fa[N],deep[N],last[N],w[N];int f[N][LGN],anc[N][LGN];int tov[E],nxt[E],len[E];int n,m,q,tot,lgn,ans;bool chosen[M];int getfather(int son){return fa[son]==son?son:fa[son]=getfather(fa[son]);}void insert(int x,int y,int z){tov[++tot]=y,len[tot]=z,nxt[tot]=last[x],last[x]=tot;}void dfs(int x){ for (int i=last[x],y;i;i=nxt[i]) if ((y=tov[i])!=anc[x][0]) anc[y][0]=x,deep[y]=deep[x]+1,f[y][0]=len[i],dfs(y);}void pre(){ lgn=trunc(log(n)/log(2)); for (int j=1;j<=lgn;j++) for (int i=1;i<=n;i++) anc[i][j]=anc[anc[i][j-1]][j-1],f[i][j]=max(f[i][j-1],f[anc[i][j-1]][j-1]);}int adjust(int x,int d){ for (int i=lgn;i>=0;i--) if (deep[anc[x][i]]>=d) ans=max(ans,f[x][i]),x=anc[x][i]; return x;}void getans(int x,int y){ ans=0; if (deep[x]>deep[y]) swap(x,y); y=adjust(y,deep[x]); if (x==y) return; for (int i=lgn;i>=0;i--) if (anc[x][i]!=anc[y][i]) ans=max(ans,max(f[x][i],f[y][i])),x=anc[x][i],y=anc[y][i]; ans=max(ans,max(f[x][0],f[y][0])),x=anc[x][0],y=anc[y][0];}int main(){ freopen("city.in","r",stdin),freopen("city.out","w",stdout); n=read(),m=read(),q=read(); for (int i=1;i<=n;i++) w[i]=read(),fa[i]=i; for (int i=1;i<=m;i++) e[i].x=read(),e[i].y=read(),e[i].l=abs(w[e[i].x]-w[e[i].y]); sort(e+1,e+1+m); for (int i=1,x,y,fx,fy;i<=m;i++) { fx=getfather(x=e[i].x),fy=getfather(y=e[i].y); if (fx!=fy) { chosen[i]=1; fa[fy]=fx; insert(x,y,e[i].l),insert(y,x,e[i].l); } } anc[1][0]=0,deep[1]=1,dfs(1); for (int i=1;i<=n;i++) fa[i]=i; for (int i=1,x,y;i<=m;i++) if (!chosen[i]) for (x=getfather(e[i].x),y=getfather(e[i].y);x!=y;x=getfather(x)) { if (deep[x]<deep[y]) swap(x,y); f[x][0]=max(e[i].l,f[x][0]); fa[x]=anc[x][0]; } pre(); for (int x,y;q--;) { x=read(),y=read(); if (getfather(x)!=getfather(y)||x==y) printf("infinitely\n"); else getans(x,y),write(ans),putchar('\n'); } fclose(stdin),fclose(stdout); return 0;}
1 0
- [51NOD1743][JZOJ4899]雪之国度
- 51nod1743 JZOJ4899【NOIP2016提高A组集训第17场11.16】雪之国度
- [51nod1743]雪之国度
- [51nod1743]雪之国度
- 【jzoj4899】【雪之国度】【最小生成树】【并查集按秩合并】
- 【51 Nod 1743】 雪之国度
- 整体二分(51nod 雪之国度)
- 51nod 1743雪之国度【最小生成树】【LCA】【并查集】
- 搜索之吝啬的国度
- 我的梦之国度
- 看僵尸三之永恒国度
- “音之国度”界面分析(二)
- [音之国度读存档]设计篇
- [音之国度读存档]实现篇
- [音之国度进度]团队探索系统
- “音之国度”游戏UI界面分析(一级界面)
- #AR游戏--音之国度#初次简单的测试
- #游戏unity-音之国度#实现语音控制
- 机器学习算法(分类算法)—神经网络之BP神经网络
- 用不带缓存的文件操作,打开文件输入字符串并按行读出。
- 结构体 queue(队列FIFO)入门
- ASPNETMVC-TIPS
- Java StringBuffer 和 StringBuilder 类
- [51NOD1743][JZOJ4899]雪之国度
- 【UML学习】用例图
- Java 数组
- WCF TIPS
- WF TIPS
- 【Noip模拟】【dp】【LIS】【矩阵快速幂】
- NOIP 2012 试做
- C C++知识点 SDL容器算法
- 机器学习算法(分类算法)—支持向量机(1)