【最短路】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;
}

 

posted @ 2013-03-14 16:55  lzqxh  阅读(214)  评论(0编辑  收藏  举报