• poj3164 最小树形图板子题


    /*

    思路很简单,也不知道哪里错了TAT

    */

    /*
    N个点通过笛卡尔坐标表示
    根节点是1,求最小树形图 
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define MAXN 105
    #define INF 0x3f3f3f3f
    using namespace std;
    struct Edge{
         int u,v;
         double cost;
         Edge(int uu=0,int vv=0,double cc=0.0):u(uu),v(vv),cost(cc){}
    }edge[MAXN*MAXN];
    struct node{
         int x,y;
    }nodes[MAXN];
    double dist(int u,int v){
         return sqrt((double)(nodes[u].x-nodes[v].x)*(nodes[u].x-nodes[v].x)+
                      (nodes[u].y-nodes[v].y)*(nodes[u].y-nodes[v].y));
    } 
    int pre[MAXN],id[MAXN],vis[MAXN];
    double in[MAXN];
    double zhuliu(int root, int nv, int ne)
    {
        double ans = 0;
        int u, v, i, cnt;
        while(true){
            //0.初始化
            for(i = 1; i <= nv; ++i) in[i] = INF;
            //1.找最小入边集
            for(i = 1; i <= ne; ++i){
                u = edge[i].u; v = edge[i].v;
                if(edge[i].cost < in[v] && u != v){
                    in[v] = edge[i].cost; pre[v] = u;
                }
            }
            for(i = 1; i <= nv; ++i)
                if(in[i]==INF && i!=root)
                    return -1;
            //2.找非根无入边点(略),因为必定有解
            //3.找环,加权,重新标号
            memset(id, -1, sizeof(id));
            memset(vis, -1, sizeof(vis));
            cnt = in[root] = 0;
            for(i = 1; i <= nv; ++i){
                ans += in[i]; v = i;
                while(vis[v] != i && v != root && id[v] == -1){
                    vis[v] = i; v = pre[v];
                }
                if(v != root && id[v] == -1){
                    for(u = pre[v]; u != v; u = pre[u])
                        id[u] = cnt;
                    id[v] = cnt++;
                }
            }
            if(cnt == 0) break; //无环,算法完成
            for(i = 1; i <= nv; ++i) 
                if(id[i] == -1) id[i] = cnt++;
            //4.缩点,遍历每一条边,重新构图
            for(i = 1; i <= ne; ++i){
                v = edge[i].v;
                edge[i].u = id[edge[i].u];
                edge[i].v = id[edge[i].v];
                if(edge[i].u != edge[i].v) edge[i].cost -= in[v];
            }
            //顶点数减少
            nv = cnt; root = id[root];
        }
        return ans;
    }
    int main(){
         int n,m,u,v;
         while(scanf("%d%d",&n,&m)==2){
             for(int i=1;i<=n;i++)
                 scanf("%d%d",&nodes[i].x,&nodes[i].y);
             int totm=0;
            for(int i=1;i<=m;i++){
                 scanf("%d%d",&u,&v);
                 if(u!=v)
                     edge[++totm]=Edge(u,v,dist(u,v));
             }
             int root=1;
             double res=zhuliu(root,n,totm);
             if(res==-1)
                 puts("poor snoopy");
             else 
                 printf("%.2lf
    ",res);
         }
         return 0;
    } 
  • 相关阅读:
    第十六周 项目一-平方根中的异常
    LeetCode之小孩分糖果
    C#中怎样将List&lt;自己定义&gt;转为Json格式 及相关函数-DataContractJsonSerializer
    (016)给定一个有序数组(递增),敲代码构建一棵具有最小高度的二叉树(keep it up)
    物化视图
    FZU2171:防守阵地 II(线段树)
    鸡尾酒排序
    Android BlueDroid(三):BlueDroid蓝牙开启过程enable
    CF Codeforces Round #256 (Div. 2) D (448D) Multiplication Table
    window.open()具体解释及浏览器兼容性问题
  • 原文地址:https://www.cnblogs.com/zsben991126/p/9804947.html
Copyright © 2020-2023  润新知