zoukankan      html  css  js  c++  java
  • 朱刘算法与最小树形图

    参考:http://hi.baidu.com/yhxhqvnjombfpzq/item/5d93ef69ceb541176895e682

           http://hi.baidu.com/lydrainbowcat/item/5fbae3fb9c159c5ec8f33753(看这篇文章有助于理解缩点过程中对于权的处理,非常清晰)

    想要自己写可是还是没有写出来,把这位同学的代码抄了一遍,终于弄懂了。。十分感谢。http://blog.sina.com.cn/s/blog_6af663940100ls4e.html

    #include<stdio.h>
    #include<algorithm>
    #include<math.h>
    #include<iostream>
    #include<string.h>
    using namespace std;
    #define MAXN 110
    #define INF 1000000000
    #define clr(a,b); memset(a,b,sizeof(a));
    struct Node
    {
        double x;
        double y;
    }node[MAXN];
    int n,m;
    int tmp;
    bool visited[MAXN],circle[MAXN];
    int pre[MAXN];
    double graph[MAXN][MAXN];
    inline double dist(int i,int j)
    {
        return sqrt((node[i].x-node[j].x)*(node[i].x-node[j].x)+(node[i].y-node[j].y)*(node[i].y-node[j].y));
    }
    inline double min(double a,double b)
    {
        if(a<b)
        return a;
        return b;
    }
    void dfs(int u)  /*深搜判断是否能够到达每个结点*/
    {
        if(visited[u])
        return;
        visited[u]=true;
        for(int i=1;i<=n;i++)
        {
            if(!visited[i]&&graph[u][i]!=INF)
            {
                dfs(i);
            }
        }
    }
    bool connect()
    {
        dfs(1);
        for(int i=1;i<=n;i++)
        {
            if(!visited[i])
            return false;
        }
        return true;
    }
    double zhu_liu()
    {
        double ans=0;int i,j,k;
        clr(circle,0);//如果某点被删除了,那么circle[i]=1
        while(1)
        {
            //求出除根节点以为每个结点入边的最小值
            for(i=2;i<=n;i++)
            {
                if(circle[i]) continue;
                graph[i][i]=INF; //把图中所有的自环都清除,这一点很重要
                pre[i]=i;  //初始化自己的前一个结点是自己
                for(j=1;j<=n;j++)
                {
                    if(circle[j])
                    continue;
                    if(graph[j][i]<graph[pre[i]][i])
                    {
                        pre[i]=j;
                    }
                }
            }
            //遍历找环
            for(i=2;i<=n;i++)
            {
                if(circle[i])
                continue;
                j=i;
                clr(visited,false);
                while(!visited[j]&&j!=1)
                {
                    visited[j]=true;
                    j=pre[j];
                }
                if(j==1)
                continue;
                i=j;
                //把环的权值都加到ans里
                ans+=graph[pre[i]][i];
                for(j=pre[i];j!=i;j=pre[j])
                {
                    ans+=graph[pre[j]][j];
                    circle[j]=1; //只用i代表这个环,其他的点都删掉,缩点
                }
                for(j=1;j<=n;j++)
                {
                    if(circle[j]) continue;
                    if(graph[j][i]!=INF)
                    graph[j][i]-=graph[pre[i]][i];
                }
                for(j=pre[i];j!=i;j=pre[j])
                {
                    for(k=1;k<=n;k++)
                    {
                        if(circle[k]) continue;
                        if(graph[j][k]!=INF)
                        graph[i][k]=min(graph[i][k],graph[j][k]);
                        if(graph[k][j]!=INF)
                        graph[k][i]=min(graph[k][i],graph[k][j] - graph[pre[j]][j]);
                    }
                }
                break;
            }
            if(i>n)
            {
                for(j=2;j<=n;j++)
                {
                    if(circle[j])
                    continue;
                    ans+=graph[pre[j]][j];
                }
                break;
            }
        }
        return ans;
    }
    int main()
    {
        int i,j,u,v;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for(i=1;i<=n;i++)
            {
                scanf("%lf%lf",&node[i].x,&node[i].y);
            }
            for(i=1;i<=n;i++)
            for(j=1;j<=n;j++)
            {
                graph[i][j]=INF;
            }
    
        while(m--)
        {
            scanf("%d%d",&u,&v);
            graph[u][v]=dist(u,v);
        }
        clr(visited,false);
        if(!connect())
        printf("poor snoopy
    ");
        else
        printf("%.2f
    ",zhu_liu());
        }
        return 0;
    }
    View Code
  • 相关阅读:
    调试php的soapCient
    thinkphp 常见问题
    git使用备忘
    org.apache.catalina.startup.Catalina异常处理
    Java多线程中join方法详解
    WebSphere 安装和配置过程
    数据库错误
    把sql输出成。sql文件
    Oracle 使用命令导入dmp文件
    pl_sql develope连接远程数据库的方法
  • 原文地址:https://www.cnblogs.com/whatthefy/p/3188136.html
Copyright © 2011-2022 走看看