bzoj-2594 水管局长数据加强版

来源:互联网 发布:visual basic编程实例 编辑:程序博客网 时间:2024/04/28 03:21

题意:

给出一个n个点m条边的无向图,边上有权值;

Q次询问,每次有两种操作:
1.求x,y两点路径上的最大值的最小值;

2.删除一条边;

保证删除的边存在,保证图时刻连通,保证不会出现重边和自环;

n≤100000,m≤1000000,Q≤100000;


题解:
这是一个动态图问题,但是由于询问操作的特殊性,我们也可以转化到树上做;

仔细看看不就是带删边的货车运输吗!

那么用LCT来维护最小生成树查询操作1就可以了;

但是LCT维护最小生成树是不能删边的;

考虑倒着处理询问,删边就成了加边;

加边会出现环,那么就将权值最大的边弹出去就好了;

弹边操作似乎比较恶心,那么将边转化成一个点,这个点连接两个点;

那么就把边权转化到点上,删除这个点的两条边就是了;

此题预处理比较糟糕(似乎离线处理的东西都这样);


代码:


#include<stdio.h>#include<string.h>#include<algorithm>#define N 110000#define Pt 330000#define which(x) (ch[fa[x]][1]==x)using namespace std;struct node{bool op;int x,y,val,no;}Q[N];struct edge{int x,y,val;bool del;friend bool operator <(edge a,edge b){if(a.x==b.x)return a.y<b.y;return a.x<b.x;}}total[N*10],temp;int fa[Pt],ch[Pt][2],val[Pt],ma[Pt],wma[Pt],ans[N],f[N];bool rt[Pt],rev[Pt];inline int read(){int x=0;char ch=getchar();while(ch<'0'||ch>'9')ch=getchar();while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}return x;}int cmp(edge a,edge b){if(a.del==b.del)return a.val<b.val;return a.del<b.del;}void Pushup(int x){ma[x]=max(val[x],max(ma[ch[x][0]],ma[ch[x][1]]));wma[x]=ma[x]==val[x]?x:(ma[x]==val[wma[ch[x][0]]]?wma[ch[x][0]]:wma[ch[x][1]]);}void reverse(int x){swap(ch[x][0],ch[x][1]);rev[x]^=1;}void Pushdown(int x){if(rev[x]){reverse(ch[x][0]);reverse(ch[x][1]);rev[x]=0;}}void down(int x){if(!rt[x])down(fa[x]);Pushdown(x);}void Rotate(int x){int f=fa[x];bool k=which(x);if(rt[f])rt[f]^=rt[x]^=1;elsech[fa[f]][which(f)]=x;ch[f][k]=ch[x][!k];ch[x][!k]=f;fa[ch[f][k]]=f;fa[x]=fa[f];fa[f]=x;Pushup(f);Pushup(x);}void Splay(int x){down(x);while(!rt[x]){int f=fa[x];if(rt[f]){Rotate(x);return ;}if(which(x)^which(f))Rotate(x);elseRotate(f);Rotate(x);}}void access(int x){int y=0;while(x){Splay(x);rt[ch[x][1]]=1,rt[y]=0;ch[x][1]=y;Pushup(x);y=x,x=fa[x];}}void Mtr(int x){access(x);Splay(x);reverse(x);}void Link(int x,int y){Mtr(x);fa[x]=y;}void Cut(int t,int x,int y){Mtr(t);access(x);Splay(t);rt[ch[t][1]]=1;fa[ch[t][1]]=0;ch[t][1]=0;access(y);Splay(t);rt[ch[t][1]]=1;fa[ch[t][1]]=0;ch[t][1]=0;Pushup(t);}int get_max(int x,int y){Mtr(x);access(y);Splay(x);return ma[x];}int get_wmax(int x,int y){Mtr(x);access(y);Splay(x);return wma[x];}int find(int x){return f[x]==x?x:find(f[x]);}void Build_Min_Tree(int n,int m){sort(total+1,total+m+1,cmp);for(int i=1;i<=n;i++)f[i]=i;int cnt=0;for(int i=1;i<=m;i++){int x=find(total[i].x),y=find(total[i].y);if(x!=y){f[x]=y;swap(total[i],total[++cnt]);if(cnt==n-1)break;}}}int main(){int n,m,q,i,j,k,cnt1,cnt2,op,x,y,v;scanf("%d%d%d",&n,&m,&q);for(i=1;i<=m;i++){total[i].x=read(),total[i].y=read(),total[i].val=read();if(total[i].x>total[i].y)swap(total[i].x,total[i].y);}sort(total+1,total+1+m);for(i=1,cnt1=cnt2=0;i<=q;i++){op=read();if(op==1)Q[i].x=read(),Q[i].y=read(),Q[i].no=++cnt1;else{Q[i].op=1;Q[i].x=read(),Q[i].y=read();if(Q[i].x>Q[i].y)swap(Q[i].x,Q[i].y);temp.x=Q[i].x,temp.y=Q[i].y;k=lower_bound(total+1,total+m+1,temp)-total;total[k].del=1,Q[i].val=total[k].val;Q[i].no=++cnt2;}}Build_Min_Tree(n,m);for(i=1;i<=n;i++)rt[i]=1,wma[i]=i;for(i=1;i<n;i++){rt[i+n]=1,wma[i+n]=i+n,val[i+n]=ma[i+n]=total[i].val;Link(i+n,total[i].x);Link(i+n,total[i].y);}for(i=q;i>=1;i--){if(Q[i].op){x=Q[i].x,y=Q[i].y;rt[Q[i].no+(n<<1)]=1,wma[Q[i].no+(n<<1)]=Q[i].no+(n<<1);val[Q[i].no+(n<<1)]=ma[Q[i].no+(n<<1)]=Q[i].val;k=get_wmax(x,y);if(val[k]>Q[i].val){Cut(k,x,y);Link(Q[i].no+(n<<1),x);Link(Q[i].no+(n<<1),y);}}else{ans[Q[i].no]=get_max(Q[i].x,Q[i].y);}}for(i=1;i<=cnt1;i++){printf("%d\n",ans[i]);}return 0;}





0 0
原创粉丝点击