您的位置:首页 > 运维架构

bzoj 3669 lct维护最小生成树

2015-05-13 23:35 218 查看
大概题意:给一个无向图,有a,b两种边权,找一条从1到n的路径,使得max(a[i])+max(b[i])最小a[i],b[i]表示该路径上的边的对应权。

如果用类似最短路的DP来做,显然每个点的状态就必须是一个集合,保存的是一个下凸的点集,表示到达这个点的最小的a,b,这样肯定会挂,但该该种做法已经无法再优化或减少状态了。

考虑枚举其中一个权值b0,然后只考虑所有b权值小于等于b0的边,然后变成简单的问题,因为这个b0不满足二分三分之类的性质,所以肯定不能每次重建图,跑DP,最终的做法是从小到大枚举一维权值,然后不断地加边进入边,维护一个当前图的最小生成树(用LCT实现)。

收获:

  1、如果一个东西不满足二分三分,可以尝试从动态的角度,暴力枚举,用数据结构保证复杂度。

/**************************************************************
Problem: 3669
User: idy002
Language: C++
Result: Accepted
Time:6680 ms
Memory:12536 kb
****************************************************************/

#include <cstdio>
#include <algorithm>
#define oo 0x3f3f3f3f
#define N 200010
using namespace std;

struct Edge {
int u, v, a, b;
Edge(){}
Edge( int u, int v, int a, int b ):u(u),v(v),a(a),b(b){}
bool operator<( const Edge &e ) const { return b<e.b; }
};
struct LCT {
int son
[2], pre
, pnt
, rtg
, ntot;
int trash
, stot;
int val
, vmx
, vnd
, uu
, vv
;

inline int newnode( int p, int va, int u, int v ) {
int nd = stot ? trash[stot--] : ++ntot;
pre[nd] = p;
son[nd][0] = son[nd][1] = pnt[nd] = 0;
rtg[nd] = 0;
val[nd] = vmx[nd] = va;
vnd[nd] = nd;
uu[nd] = u;
vv[nd] = v;
return nd;
}
void update( int nd ) {
vmx[nd] = val[nd];
vmx[nd] = max( vmx[nd], vmx[son[nd][0]] );
vmx[nd] = max( vmx[nd], vmx[son[nd][1]] );
if( vmx[nd]==val[nd] )
vnd[nd] = nd;
else if( vmx[nd]==vmx[son[nd][0]] )
vnd[nd] = vnd[son[nd][0]];
else
vnd[nd] = vnd[son[nd][1]];
}
void rotate( int nd, int d ) {
int p = pre[nd];
int s = son[nd][!d];
int ss = son[s][d];

son[nd][!d] = ss;
son[s][d] = nd;
if( p ) son[p][ nd==son[p][1] ] = s;
else pnt[s]=pnt[nd], pnt[nd]=0;

pre[nd] = s;
pre[s] = p;
if( ss ) pre[ss] = nd;

update(nd);
update(s);
}
void bigp( int nd ) {
if( pre[nd] ) bigp(pre[nd]);
if( rtg[nd] ) {
rtg[son[nd][0]] ^= 1;
rtg[son[nd][1]] ^= 1;
swap( son[nd][0], son[nd][1] );
rtg[nd] = 0;
}
}
void splay( int nd, int top=0 ) {
bigp(nd);
while( pre[nd]!=top ) {
int p=pre[nd];
int nl=nd==son[p][0];
if( pre[p]==top ) {
rotate( p, nl );
} else {
int pp=pre[p];
int pl=p==son[pp][0];
if( nl==pl ) {
rotate( pp, pl );
rotate( p, nl );
} else {
rotate( p, nl );
rotate( pp, pl );
}
}
}
}
void access( int nd ) {
int u = nd;
int v = 0;
while( u ) {
splay( u );
int s=son[u][1];
if( s ) {
pre[s] = 0;
pnt[s] = u;
}
son[u][1] = 0;
if( v ) {
pre[v] = u;
pnt[v] = 0;
}
son[u][1] = v;
update(u);
v = u;
u = pnt[u];
}
splay( nd );
}
void makeroot( int u ) {
access(u);
rtg[u] ^= 1;
}
void init( int n ) {
ntot = n;
val[0] = -1;
}
int findroot( int u ) {
while( pre[u] ) u=pre[u];
while( pnt[u] ) {
u=pnt[u];
while( pre[u] ) u=pre[u];
}
return u;
}
bool sameroot( int u, int v ) {
return findroot(u)==findroot(v);
}
int query( int s, int t ) {
makeroot(s);
access(t);
return vmx[t];
}
void addedge( int u, int v, int w ) {
//      fprintf( stderr, "addedge( %d %d %d )\n", u, v, w );
if( sameroot(u,v) ) {
if( query(u,v)<=w ) return;
makeroot(u);
access(v);
int nd = vnd[v];
int l = uu[nd];
int r = vv[nd];
makeroot(l);
access(r);
bigp(l);
int e = son[r][0];
while( son[e][1] ) e=son[e][1];
splay(e);
pre[l] = pre[r] = 0;
trash[++stot] = e;
}
makeroot(u);
makeroot(v);
int nd = newnode(0,w,u,v);
pnt[u] = nd;
pnt[v] = nd;
}
void print() {
fprintf( stderr, "\n" );
for( int i=1; i<=ntot; i++ ) {
int nd = i;
for( int j=1; j<=stot; j++ )
if( i==trash[j] )
goto Next;
fprintf( stderr, "%d pnt=%d pre=%d ls=%d rs=%d rtg=%d val=%d vmx=%d vnd=%d uu=%d vv=%d\n",
nd, pnt[nd], pre[nd], son[nd][0], son[nd][1], rtg[nd], val[nd], vmx[nd], vnd[nd], uu[nd], vv[nd] );
Next:;
}
}
}T;

int n, m;
Edge edge
;

int main() {
scanf( "%d%d", &n, &m );
for( int i=1,u,v,a,b; i<=m; i++ ) {
scanf( "%d%d%d%d", &u, &v, &a, &b );
edge[i] = Edge(u,v,a,b);
}
sort( edge+1, edge+1+m );
T.init(n);
int ans = oo;
for( int i=1,j; i<=m; i=j ) {
for( j=i; j<=m; j++ ) {
if( edge[j].b==edge[i].b )
T.addedge(edge[j].u,edge[j].v,edge[j].a);
else break;
}
if( !T.sameroot(1,n) ) continue;
ans = min( ans, edge[i].b+T.query(1,n) );
}
printf( "%d\n", ans==oo ? -1 : ans );
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: