标签:
大概题意:给一个无向图,有a,b两种边权,找一条从1到n的路径,使得max(a[i])+max(b[i])最小a[i],b[i]表示该路径上的边的对应权。
如果用类似最短路的DP来做,显然每个点的状态就必须是一个集合,保存的是一个下凸的点集,表示到达这个点的最小的a,b,这样肯定会挂,但该该种做法已经无法再优化或减少状态了。
考虑枚举其中一个权值b0,然后只考虑所有b权值小于等于b0的边,然后变成简单的问题,因为这个b0不满足二分三分之类的性质,所以肯定不能每次重建图,跑DP,最终的做法是从小到大枚举一维权值,然后不断地加边进入边,维护一个当前图的最小生成树(用LCT实现)。
收获:
1、如果一个东西不满足二分三分,可以尝试从动态的角度,暴力枚举,用数据结构保证复杂度。
1 /************************************************************** 2 Problem: 3669 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:6680 ms 7 Memory:12536 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 #define oo 0x3f3f3f3f 13 #define N 200010 14 using namespace std; 15 16 struct Edge { 17 int u, v, a, b; 18 Edge(){} 19 Edge( int u, int v, int a, int b ):u(u),v(v),a(a),b(b){} 20 bool operator<( const Edge &e ) const { return b<e.b; } 21 }; 22 struct LCT { 23 int son[N][2], pre[N], pnt[N], rtg[N], ntot; 24 int trash[N], stot; 25 int val[N], vmx[N], vnd[N], uu[N], vv[N]; 26 27 inline int newnode( int p, int va, int u, int v ) { 28 int nd = stot ? trash[stot--] : ++ntot; 29 pre[nd] = p; 30 son[nd][0] = son[nd][1] = pnt[nd] = 0; 31 rtg[nd] = 0; 32 val[nd] = vmx[nd] = va; 33 vnd[nd] = nd; 34 uu[nd] = u; 35 vv[nd] = v; 36 return nd; 37 } 38 void update( int nd ) { 39 vmx[nd] = val[nd]; 40 vmx[nd] = max( vmx[nd], vmx[son[nd][0]] ); 41 vmx[nd] = max( vmx[nd], vmx[son[nd][1]] ); 42 if( vmx[nd]==val[nd] ) 43 vnd[nd] = nd; 44 else if( vmx[nd]==vmx[son[nd][0]] ) 45 vnd[nd] = vnd[son[nd][0]]; 46 else 47 vnd[nd] = vnd[son[nd][1]]; 48 } 49 void rotate( int nd, int d ) { 50 int p = pre[nd]; 51 int s = son[nd][!d]; 52 int ss = son[s][d]; 53 54 son[nd][!d] = ss; 55 son[s][d] = nd; 56 if( p ) son[p][ nd==son[p][1] ] = s; 57 else pnt[s]=pnt[nd], pnt[nd]=0; 58 59 pre[nd] = s; 60 pre[s] = p; 61 if( ss ) pre[ss] = nd; 62 63 update(nd); 64 update(s); 65 } 66 void bigp( int nd ) { 67 if( pre[nd] ) bigp(pre[nd]); 68 if( rtg[nd] ) { 69 rtg[son[nd][0]] ^= 1; 70 rtg[son[nd][1]] ^= 1; 71 swap( son[nd][0], son[nd][1] ); 72 rtg[nd] = 0; 73 } 74 } 75 void splay( int nd, int top=0 ) { 76 bigp(nd); 77 while( pre[nd]!=top ) { 78 int p=pre[nd]; 79 int nl=nd==son[p][0]; 80 if( pre[p]==top ) { 81 rotate( p, nl ); 82 } else { 83 int pp=pre[p]; 84 int pl=p==son[pp][0]; 85 if( nl==pl ) { 86 rotate( pp, pl ); 87 rotate( p, nl ); 88 } else { 89 rotate( p, nl ); 90 rotate( pp, pl ); 91 } 92 } 93 } 94 } 95 void access( int nd ) { 96 int u = nd; 97 int v = 0; 98 while( u ) { 99 splay( u ); 100 int s=son[u][1]; 101 if( s ) { 102 pre[s] = 0; 103 pnt[s] = u; 104 } 105 son[u][1] = 0; 106 if( v ) { 107 pre[v] = u; 108 pnt[v] = 0; 109 } 110 son[u][1] = v; 111 update(u); 112 v = u; 113 u = pnt[u]; 114 } 115 splay( nd ); 116 } 117 void makeroot( int u ) { 118 access(u); 119 rtg[u] ^= 1; 120 } 121 void init( int n ) { 122 ntot = n; 123 val[0] = -1; 124 } 125 int findroot( int u ) { 126 while( pre[u] ) u=pre[u]; 127 while( pnt[u] ) { 128 u=pnt[u]; 129 while( pre[u] ) u=pre[u]; 130 } 131 return u; 132 } 133 bool sameroot( int u, int v ) { 134 return findroot(u)==findroot(v); 135 } 136 int query( int s, int t ) { 137 makeroot(s); 138 access(t); 139 return vmx[t]; 140 } 141 void addedge( int u, int v, int w ) { 142 // fprintf( stderr, "addedge( %d %d %d )\n", u, v, w ); 143 if( sameroot(u,v) ) { 144 if( query(u,v)<=w ) return; 145 makeroot(u); 146 access(v); 147 int nd = vnd[v]; 148 int l = uu[nd]; 149 int r = vv[nd]; 150 makeroot(l); 151 access(r); 152 bigp(l); 153 int e = son[r][0]; 154 while( son[e][1] ) e=son[e][1]; 155 splay(e); 156 pre[l] = pre[r] = 0; 157 trash[++stot] = e; 158 } 159 makeroot(u); 160 makeroot(v); 161 int nd = newnode(0,w,u,v); 162 pnt[u] = nd; 163 pnt[v] = nd; 164 } 165 void print() { 166 fprintf( stderr, "\n" ); 167 for( int i=1; i<=ntot; i++ ) { 168 int nd = i; 169 for( int j=1; j<=stot; j++ ) 170 if( i==trash[j] ) 171 goto Next; 172 fprintf( stderr, "%d pnt=%d pre=%d ls=%d rs=%d rtg=%d val=%d vmx=%d vnd=%d uu=%d vv=%d\n", 173 nd, pnt[nd], pre[nd], son[nd][0], son[nd][1], rtg[nd], val[nd], vmx[nd], vnd[nd], uu[nd], vv[nd] ); 174 Next:; 175 } 176 } 177 }T; 178 179 int n, m; 180 Edge edge[N]; 181 182 int main() { 183 scanf( "%d%d", &n, &m ); 184 for( int i=1,u,v,a,b; i<=m; i++ ) { 185 scanf( "%d%d%d%d", &u, &v, &a, &b ); 186 edge[i] = Edge(u,v,a,b); 187 } 188 sort( edge+1, edge+1+m ); 189 T.init(n); 190 int ans = oo; 191 for( int i=1,j; i<=m; i=j ) { 192 for( j=i; j<=m; j++ ) { 193 if( edge[j].b==edge[i].b ) 194 T.addedge(edge[j].u,edge[j].v,edge[j].a); 195 else break; 196 } 197 if( !T.sameroot(1,n) ) continue; 198 ans = min( ans, edge[i].b+T.query(1,n) ); 199 } 200 printf( "%d\n", ans==oo ? -1 : ans ); 201 }
标签:
原文地址:http://www.cnblogs.com/idy002/p/4502101.html