BZOJ 3669 膜法森林

Link

Solution

找出一条从11nnmax(ai)+max(bi)max(a_i)+max(b_i)最小的道路 两个量不好一起算, 可以通过枚举aia_i,求出相应最小的bib_i来做。 用LCT维护,边转点,在点上记录边的bib_i。 按照aia_i排个序,然后依次枚举边ee,设 , 为起点,终点 如果 不联通,那就连上 否则如果 的道路上bib_i最大值大于当前的beb_e,就切掉 否则就continue 然后如果没有continue的话,把这个边连上,更新答案。

Tips

很早就做过,复习拿出来看看打算写写新的下传标记的方法。 于是就惨了 在 里是只有 需要下传,但在LCT里,按照那个原则,在 都要下传。也就是说只要 的父子关系要变动,之前就必须要 。于是就很愉快地debug了大半上午。

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
//Code by Lucida
#include<bits/stdc++.h>
#define get(x) scanf("%d",&x)
#define put(x) printf("%d",x)
#define getc() getchar()
#define putc(x) putchar(x)
#define puts(x) printf("%s",x)

template <class T> inline bool chkmx(T &a,const T &b){return a<b?a=b,1:0;}
template <class T> inline bool chkmn(T &a,const T &b){return a>b?a=b,1:0;}

using std::max;
using std::min;
using std::sort;
using std::swap;
using std::pair;
using std::make_pair;

const int INF=0x1f1f1f1f,MAXN=50000+11,MAXM=100000+11;
//修改父子关系 必须down().
namespace LCT
{
const int SIZE=MAXN+MAXM;
typedef pair<int,int> Data;
struct Node
{
Node *son[2],*fa;
bool rev;
Data self,imax;
int kind(){return fa->son[1]==this;}
bool isrt(){return fa->son[0]!=this && fa->son[1]!=this;}
Node()
{
rev=0;
son[0]=son[1]=fa=0;
self=imax=make_pair(-INF,0);
}
void Rev()
{
rev^=1;
swap(son[0],son[1]);
}
void down()
{
if(rev)
{
son[0]->Rev();
son[1]->Rev();
rev=0;
}
}
void up(){imax=max(self,max(son[0]->imax,son[1]->imax));}
}*POOL=(Node*)malloc(SIZE*sizeof(Node)),*ME=POOL,*null=new(ME++) Node,*node[SIZE];

Node *newNode(Data v=make_pair(-INF,0))
{
static Node *cur;cur=ME++;
cur->self=cur->imax=v;
cur->rev=0;
cur->son[0]=cur->son[1]=cur->fa=null;
return cur;
}
void Trans(Node *pos)
{
static Node *f,*grf;
static int d;
f=pos->fa,grf=f->fa;
f->down(),pos->down();
d=pos->kind();//有可能变化!!
if(!f->isrt())
grf->son[f->kind()]=pos;
pos->fa=grf;
f->son[d]=pos->son[!d],pos->son[!d]->fa=f;
pos->son[!d]=f,f->fa=pos;
f->up();
pos->up();
}
void Splay(Node *pos)
{
while(!pos->isrt())
{
Node *f=pos->fa;
if(!f->isrt())
Trans(pos->kind()==f->kind()?f:pos);//isrt..
Trans(pos);
}
}
void Access(Node *pos)
{
Node *pred=null;
while(pos!=null)
{
Splay(pos);
pos->down(),pos->son[1]=pred,pos->up();
pred=pos;
pos=pos->fa;
}
}
void BeRoot(Node *pos)
{
Access(pos);
Splay(pos);
pos->Rev();
}
Node *FindRoot(Node *pos)
{
Access(pos);Splay(pos);
while(pos->son[0]!=null)
pos=pos->son[0];
Splay(pos);
return pos;
}
void Link(Node *p1,Node *p2)
{
BeRoot(p1);
p1->fa=p2;
Splay(p2);
}
void Cut(Node *p1,Node *p2)
{
BeRoot(p1);
Access(p2);
Splay(p2);
p2->down();p2->son[0]=null;
p1->fa->down();p1->fa=null;
p2->up();
}

Data Query(Node *p1,Node *p2)
{
BeRoot(p1);
Access(p2);
Splay(p2);
return p2->imax;
}
}using namespace LCT;
struct Edges{int from,to,va,vb;}edges[MAXM];
bool operator <(const Edges &e1,const Edges &e2)
{
if(e1.va!=e2.va) return e1.va<e2.va;
return e1.vb<e2.vb;
}
int main()
{
freopen("input","r",stdin);
int n,m;get(n),get(m);
#define edge(i) (i+n)
#define point(i) (i)
for(int i=1;i<=m;++i)
get(edges[i].from),get(edges[i].to),get(edges[i].va),get(edges[i].vb);
sort(edges+1,edges+1+m);
for(int i=1;i<=n;++i)
node[point(i)]=newNode(make_pair(-INF,-i));
int Ans=INF;
for(int i=1;i<=m;++i)
{
int from=edges[i].from,to=edges[i].to,va=edges[i].va,vb=edges[i].vb;
if(FindRoot(node[point(from)])==FindRoot(node[point(to)]))
{
Data res;
if((res=Query(node[point(from)],node[point(to)])).first>vb)
{
int idx=res.second;
Cut(node[point(edges[idx].from)],node[edge(idx)]);
Cut(node[point(edges[idx].to)],node[edge(idx)]);
}
else continue;
}

Node *curEdge=node[edge(i)]=newNode(make_pair(vb,i));
Link(node[point(from)],curEdge);
Link(node[point(to)],curEdge);

if(FindRoot(node[point(1)])==FindRoot(node[point(n)]))
chkmn(Ans,va+Query(node[point(1)],node[point(n)]).first);
}
put(Ans==INF?-1:Ans),putc('\n');
return 0;
}