【最短路】world final 2012 G.Minimum Cost Flow
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=547&page=show_problem&problem=4043
不愧是fianl题。。算个最短路都这么。。。蛋疼!!。更蛋疼的是我计算距离的函数竟然返回int类型=。=,无缘无故wa了几次。。
View Code
//By Lin #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<set> #include<vector> #include<map> #include<queue> #define sqr(x) ((x)*(x)) #define Rep(i,n) for(int i = 0; i<n; i++) #define foreach(i,n) for( __typeof(n.begin()) i = n.begin(); i!=n.end(); i++) #define X first #define Y second #define mp(x,y) make_pair(x,y) using namespace std; typedef long long LL; typedef pair<int,int> pii; #define N 405 #define M 500010 #define eps 1e-9 int ecnt; struct Edge{ int to; Edge *next; }*mat[N],edges[M*2]; void link(int x,int to){ edges[ecnt].to = to; edges[ecnt].next = mat[x]; mat[x] = &edges[ecnt++]; } double dis[N]; bool mark[N]; vector<int> v[N]; int cnt,p[N],n,m,num[N],tol[N],height[N]; struct Node{ int x,y,z,tol; void init(){ scanf("%d%d%d%d", &x, &y, &z , &tol ); } }data[N]; double dist( const Node &a , const Node &b){ return sqrt( sqr(a.x-b.x+0.0)+sqr(a.y-b.y+0.0)+sqr(a.z-b.z+0.0) ); } int Find(int x){ return p[x]=(p[x]==x?x:Find(p[x])); } int sgn( double x){ if ( fabs(x)<eps ) return 0; return x>0?1:-1; } void check(double &x, double y){ if ( sgn(x)<0 || x > y ) x = y; } double solve(int H){ Rep(i,n) p[i] = i; memset( tol, 0 , sizeof(tol) ); memset( num, 0 , sizeof(num) ); cnt = 0; Rep(i,n){ if ( data[i].z > H ) continue; for( Edge *it = mat[i]; it ; it = it->next ){ int to = it->to; if ( data[to].z > H ) continue; p[Find(to)] = Find(i); } } Rep(i,n) { if ( p[i] != i ) continue; v[Find(i)].clear(); Rep(j,n) if ( Find(j) == Find(i) ) { v[Find(i)].push_back(j); tol[Find(i)] += data[j].tol; } } Rep(i,n) dis[i] = -1; dis[0] = 0; memset( mark , false, sizeof(mark) ); while ( true ){ int i = -1 , j; Rep(g,n) { if ( sgn(dis[g])<0 || mark[g] ) continue; if ( i == -1 || dis[g]<dis[i] ) i = g; } if ( i == -1 ) break; double now = dis[i]+tol[Find(i)]*0.5-(i?0.5:0); if ( Find(i) == Find(n-1) ) return now; mark[i] = true; // if ( ++num[Find(i)] > 2 ) continue; foreach(it,v[Find(i)]){ int g = *it; if ( data[g].tol == 0 || data[g].tol == 1 && i && g==i ) continue; Rep(h,n){ if ( data[h].z > H ) continue; if ( Find(h) == Find(i) || data[h].tol == 0 ) continue; if ( mark[h] ) continue; check( dis[h] , now+dist(data[g],data[h])-0.5 ); } } } return -1; } int main(){ int tt = 0; while ( ~scanf("%d%d", &n, &m ) ){ Rep(i,n) { data[i].init(); height[i] = data[i].z; } ecnt = 0; memset( mat , 0 , sizeof(mat) ); while ( m -- ) { int x,y; scanf("%d%d", &x, &y ); x--,y--; link( x, y ); link( y, x ); } sort( height , height+n ); int K = unique(height,height+n)-height; double ans = -1; Rep(i,K){ if ( max(data[0].z,data[n-1].z)>height[i] ) continue; double k = solve( height[i] ); if ( sgn(k)>=0 ) check( ans , k ); } printf("Case %d: ", ++tt ); if ( sgn(ans)>=0 ) printf("%.4f\n" , ans ); else printf("impossible\n"); } return 0; }