题意:
给出一张n节点、m条代权无向边的无向联通图 和q个任务
1:询问一条x到y的路径 并使路径上最大权值最小 要求输出路径上最大权值
2:宣布x到y的路径报废题目保证该图永远联通
题解:
这是道凶残的题目 用了我一整天的时间
虽然AK大神表示这是模板题看到最大权值最小 可能会想到二分(其实我是写题解的时候才想到的 因为大表讲课的时候讲过怎么做)
但是好像二分不好判断是否可行 要判断貌似要O(m)的时间 对这个庞大的数据是很难A的于是
我们可以倒着来做 从最后一个任务开始
显然 若是要x到y最大值最小 就要保证图为最小生成树 并用动态树维护 路径上的最大值
任务1就直接从动态树上取答案
任务2 就添加一个水管 为了保证是最小生成树 算出x到y的最大值
如果比当前水管权值大 那么删掉最大的那个水管 并且link(x,y)
这题目虽然给了25s的时限 但是它竟然连输入都要优化 可见卡时卡得多凶残 这也体现了打动态树要打好常数的重要性
这题我TLE了一晚上 打了AK大神说的二分优化 但是还是T 当时已经快崩溃了 打了一天就做了一题还TLE(不难发现我后面的代码二分用的是wtf - -) 一气之下往全部函数前面加了个inline 又交了一次 本来不打算A的 但是它竟然过了 而且还是26s过的... 反正它是显示accept了... 话说JY大神优化了一晚上 刷到了第三名 9s!orz
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <map> 3 #include <algorithm> 4 using std::sort; 5 using std::map; 6 struct info{ 7 int lc,rc,fat,max,key,tag,root; 8 info(const int a=0,const int b=0,const int c=0,const int d=0,const int e=0,const int f=0,const int g=1): 9 lc(a),rc(b),fat(c),max(d),key(e),tag(f),root(g){} 10 }tree[200001]; 11 struct inli{ 12 int x,y,lll; 13 inli(const int a=0,const int b=0,const int c=0): 14 x(a),y(b),lll(c){} 15 }line[1000001],ask[100001]; 16 inline bool operator <(inli a,inli b){ 17 return a.x<b.x || (a.x==b.x && a.y<b.y); 18 } 19 //map<inli,int> ma; 20 int n,m,q,nn,nb,lon[1000001],bo[100001],ans[100001],na,ma[2000001]; 21 inline void clean(){ 22 tree[0]=info(0,0,0,0,0,0,0); 23 } 24 inline void swap(int &a,int &b){ 25 int x=a; 26 a=b,b=x; 27 } 28 inline void pushdown(int t){ 29 if (tree[t].tag){ 30 tree[t].tag=0; 31 tree[tree[t].lc].tag^=1; 32 tree[tree[t].rc].tag^=1; 33 swap(tree[t].lc,tree[t].rc); 34 } 35 clean(); 36 } 37 inline void maintain(int t){ 38 tree[t].max=t; 39 int ll=tree[t].lc,rr=tree[t].rc; 40 if (tree[tree[ll].max].key>tree[tree[t].max].key) tree[t].max=tree[ll].max; 41 if (tree[tree[rr].max].key>tree[tree[t].max].key) tree[t].max=tree[rr].max; 42 } 43 inline void left(int t){ 44 int fa=tree[t].fat,r=tree[t].rc; 45 tree[t].rc=tree[r].lc; 46 tree[tree[r].lc].fat=t; 47 tree[r].lc=t; 48 tree[t].fat=r; 49 if (tree[t].root) tree[t].root=0,tree[r].root=1; 50 else if (tree[fa].lc==t) tree[fa].lc=r; 51 else tree[fa].rc=r; 52 tree[r].fat=fa; 53 clean(); 54 maintain(t); 55 maintain(r); 56 } 57 inline void right(int t){ 58 int fa=tree[t].fat,l=tree[t].lc; 59 tree[t].lc=tree[l].rc; 60 tree[tree[l].rc].fat=t; 61 tree[l].rc=t; 62 tree[t].fat=l; 63 if (tree[t].root) tree[t].root=0,tree[l].root=1; 64 else if (tree[fa].lc==t) tree[fa].lc=l; 65 else tree[fa].rc=l; 66 tree[l].fat=fa; 67 clean(); 68 maintain(t); 69 maintain(l); 70 } 71 inline void splay(int t){ 72 while (!tree[t].root){ 73 int fa=tree[t].fat,gr=tree[fa].fat; 74 pushdown(gr); 75 pushdown(fa); 76 pushdown(t); 77 if (tree[fa].root){ 78 if (tree[fa].lc==t) right(fa); 79 else left(fa); 80 }else if (tree[gr].lc==fa){ 81 if (tree[fa].lc==t) right(gr),right(fa); 82 else left(fa),right(gr); 83 }else if (tree[fa].rc==t) left(gr),left(fa); 84 else right(fa),left(gr); 85 } 86 } 87 inline void access(int x){ 88 int y; 89 for (y=x,x=0;y;x=y,y=tree[y].fat){ 90 splay(y); 91 pushdown(y); 92 tree[tree[y].rc].root=1; 93 tree[y].rc=x; 94 tree[x].root=0; 95 maintain(y); 96 } 97 } 98 inline void makeroot(int t){ 99 access(t); 100 splay(t); 101 tree[t].tag^=1; 102 } 103 inline void link(int xx,int yy){ 104 makeroot(xx); 105 splay(xx); 106 splay(yy); 107 pushdown(yy); 108 tree[tree[yy].rc].root=1; 109 tree[yy].rc=xx; 110 tree[xx].fat=yy; 111 tree[xx].root=0; 112 maintain(yy); 113 } 114 inline void cutting(int t){ 115 splay(t); 116 pushdown(t); 117 int l=tree[t].lc,r=tree[t].rc; 118 if (l) tree[l].fat=tree[t].fat,tree[l].root=1; 119 if (r) tree[r].fat=0,tree[r].root=1; 120 } 121 inline void cutlink(int xx,int yy,int lo){ 122 makeroot(xx); 123 access(yy); 124 splay(yy); 125 int save=tree[yy].max; 126 if (tree[save].key<=lo) return; 127 cutting(save); 128 tree[save]=info(0,0,0,save,lo,0,1); 129 link(save,xx); 130 link(save,yy); 131 } 132 inline int getfat(int t){ 133 while (tree[t].fat) t=tree[t].fat; 134 return t; 135 } 136 inline bool check(int xx,int yy){ 137 makeroot(xx); 138 access(yy); 139 splay(yy); 140 return getfat(xx)==yy; 141 } 142 inline int wtf(inli t){ 143 int l=0,r=m,mid; 144 while (l<r-1){ 145 mid=(l+r)/2; 146 if (line[mid]<t) l=mid; 147 else r=mid; 148 } 149 return r; 150 } 151 inline void build(){ 152 for (int i=1;i<=n;i++) tree[i]=info(0,0,0,i,0,0,1); 153 nn=n; 154 for (int i=1;i<=m;i++){ 155 int save=wtf(line[i]); 156 if (!ma[save]){ 157 if (check(line[i].x,line[i].y)) cutlink(line[i].x,line[i].y,lon[i]); 158 else{ 159 ++nn; 160 tree[nn]=info(0,0,0,nn,lon[i],0,1); 161 link(nn,line[i].x); 162 link(nn,line[i].y); 163 } 164 }else ask[ma[save]].lll=lon[i]; 165 } 166 } 167 inline int getint(){ 168 char ch = getchar(); 169 for ( ; ch > '9' || ch < '0'; ch = getchar()); 170 int tmp = 0; 171 for ( ; '0' <= ch && ch <= '9'; ch = getchar()) 172 tmp = tmp * 10 + int(ch) - 48; 173 return tmp; 174 } 175 int main(){ 176 freopen("tube.in","r",stdin); 177 freopen("bz2594.out","w",stdout); 178 int i,j,xx,yy; 179 scanf("%d%d%d ",&n,&m,&q); 180 for (i=1;i<=m;i++){ 181 xx=getint(); 182 yy=getint(); 183 lon[i]=getint(); 184 if (xx>yy) swap(xx,yy); 185 line[i]=inli(xx,yy,lon[i]); 186 } 187 sort(line+1,line+m+1); 188 for (i=1;i<=m;i++) lon[i]=line[i].lll; 189 for (i=1;i<=q;i++){ 190 bo[i]=getint(); 191 xx=getint(); 192 yy=getint(); 193 if (xx>yy) swap(xx,yy); 194 ask[i]=inli(xx,yy); 195 if (bo[i]==2) ma[wtf(ask[i])]=i; 196 } 197 build(); 198 for (i=q;i;i--){ 199 if (i==1){ 200 i=1; 201 } 202 xx=ask[i].x,yy=ask[i].y; 203 if (bo[i]==1){ 204 makeroot(xx); 205 access(yy); 206 splay(yy); 207 ans[++na]=tree[tree[yy].max].key; 208 }else cutlink(xx,yy,ask[i].lll); 209 } 210 for (i=na;i;i--) printf("%d ",ans[i]); 211 }