POJ 3164 Command Network 最小树形图模板

最小树形图求的是有向图的最小生成树,跟无向图求最小生成树有很大的区别。

步骤大致如下:

1.求除了根节点以外每个节点的最小入边,记录前驱

2.判断除了根节点,是否每个节点都有入边,如果存在没有入边的点,说明树形图不存在,退出。

3.沿着节点的前驱找,如果发现环,把环缩点。

4.如果不存在环,结束。否则,跳到1.

 

其实我是来贴模板的。。。

比较好的讲解:最小树型图的求解与实现

代码讲解比较好的:hdu4009 Transfer water ( 最小树形图的模板 )

用IO优化时死活TLE,改了scanf就过了,后来用!=EOF发现数据不全,怪不得TLE了,囧

 

 

#include <set>
#include <map>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>

using namespace std;

typedef long long ll;
typedef unsigned long long ull;

#define debug puts("here")
#define rep(i,n) for(int i=0;i<n;i++)
#define rep1(i,n) for(int i=1;i<=n;i++)
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define foreach(i,vec) for(unsigned i=0;i<vec.size();i++)
#define pb push_back
#define RD(n) scanf("%d",&n)
#define RD2(x,y) scanf("%d%d",&x,&y)
#define RD3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define RD4(x,y,z,w) scanf("%d%d%d%d",&x,&y,&z,&w)
#define All(vec) vec.begin(),vec.end()
#define MP make_pair
#define PII pair<int,int>
#define PQ priority_queue
#define cmax(x,y) x = max(x,y)
#define cmin(x,y) x = min(x,y)
#define Clear(x) memset(x,0,sizeof(x))
/*

#pragma comment(linker, "/STACK:1024000000,1024000000")

int size = 256 << 20; // 256MB
char *p = (char*)malloc(size) + size;
__asm__("movl %0, %%esp\n" :: "r"(p) );

*/

char IN;
bool NEG;
inline void Int(int &x){
    NEG = 0;
    while(!isdigit(IN=getchar()))
        if(IN=='-')NEG = 1;
    x = IN-'0';
    while(isdigit(IN=getchar()))
        x = x*10+IN-'0';
    if(NEG)x = -x;
}
inline void LL(ll &x){
    NEG = 0;
    while(!isdigit(IN=getchar()))
        if(IN=='-')NEG = 1;
    x = IN-'0';
    while(isdigit(IN=getchar()))
        x = x*10+IN-'0';
    if(NEG)x = -x;
}

/******** program ********************/

const int MAXN = 105;
const double INF = 1e50;

int pre[MAXN],id[MAXN],use[MAXN];
int px[MAXN],py[MAXN];
double in[MAXN];

struct Edge{
    int x,y;
    double cost;
    Edge(){}
    Edge(int _x,int _y,double _cost):x(_x),y(_y),cost(_cost){}
}g[MAXN*MAXN];
double treeDiagrm(int root,int n,int m){
    double ans = 0;
    while(true){
        rep1(i,n)
            in[i] = INF;

        rep1(i,m){
            int x = g[i].x , y = g[i].y;
            double cost = g[i].cost;
            if(cost<in[y]&&y!=x)
                pre[y] = x , in[y] = cost;
        }
        in[root] = 0 , pre[root] = root;
        rep1(x,n){
            if(in[x]>1e20)return -1;
            ans += in[x];
        }
        Clear(use);
        Clear(id);
        int tot = 0;
        rep1(i,n){
            if(use[i])continue;
            int x = i;
            while(!use[x])use[x] = i , x = pre[x];
            if(use[x]!=i||x==root)continue;
            id[x] = ++ tot;
            for(int t=pre[x];t!=x;t=pre[t])
                id[t] = tot;
        }
        if(!tot)break;
        rep1(i,n)if(!id[i])id[i] = ++ tot;

        rep1(i,m){
            g[i].cost -= in[g[i].y];
            g[i].x = id[g[i].x];
            g[i].y = id[g[i].y];
        }
        n = tot;
        root = id[root];
    }
    return ans;
}

double cal(int x,int y){
    return sqrt(0.0+x*x+y*y);
}

int main(){

#ifndef ONLINE_JUDGE
    freopen("sum.in","r",stdin);
    //freopen("sum.out","w",stdout);
#endif

    int x,y,n,m;
    while(~RD2(n,m)){
        rep1(i,n)
            RD2(px[i],py[i]);
        rep1(i,m){
            RD2(x,y);
            g[i] = Edge(x,y,cal(px[x]-px[y],py[x]-py[y]));
        }
        double ans = treeDiagrm(1,n,m);
        if(ans>0)
            printf("%.2lf\n",ans);
        else puts("poor snoopy");
    }

    return 0;
}

 

  

 

 

 

posted @ 2013-09-09 23:15  yejinru  阅读(238)  评论(0编辑  收藏  举报