Freckles 牛客 dijkstra(WA)换prim(AC) (dijkstra是最短路径,与最小生成树本质不同)

 WA,给的那个测试用例可以通过(因为给的用例就是简单的三个点,头到尾,最短路径等于最小生成树)

#include<bits/stdc++.h>
using namespace std;
/*
求把点连起来的最小路径,kruskal?dijkstra?
*/



int main(){
    //kruskal用到并查集
    //dijkstra不用
    int n;
    
        while(cin>>n)
        {
            vector<vector<float>>dist(n,vector<float>(n,0));//存放点i到j的距离
            vector<vector<float>>pos(n,vector<float>(2,0));//存放点的坐标
            
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<2;j++)
                {
                    cin>>pos[i][j];
                }
            }
            
            for(int i=0;i<n;i++)//初始化dist矩阵,i到j的距离
            {
                for(int j=0;j<n;j++)
                {
                    if(i==j){continue;}
                    int dx=pos[i][0]-pos[j][0];
                    int dy=pos[i][1]-pos[j][1];
                    dist[i][j]=sqrt(dx*dx+dy*dy);
                }
            }
            //cout<<setprecision(3)<<dist[1][0];
            
            //初始化dis数组,第一个dis数组以0号坐标点开始
            float ans=0;
            
            vector<int>visted(n,0);
            visted[0]=1;
            vector<float>dis(n,0);
            int tmppos;
            vector<int>load(n,0);
            
            for(int i=1;i<n;i++)
            {
                dis[i]=dist[0][i];
            }
            
            for(int t=1;t<n;t++)//循环n
            {    int mindis=INT_MAX;
                for(int i=1;i<n;i++)
                {
                    //找到dis中最近的
                    if(visted[i]!=1&&dis[i]<mindis)
                    {
                        mindis=dis[i];
                        tmppos=i;
                    }
                }
                 visted[tmppos]=1;
                 //cout<<dis[tmppos];
                 //ans+=dis[tmppos];
                 load[t]=tmppos;
                //找到最近的下一个点tmppos,从这里更新dis
                for(int i=1;i<n;i++)
                {
                    if(visted[i]!=1&&dis[tmppos]+dist[tmppos][i]<dis[i])//经过tmppos这个点的中转,更新dis数组
                    {//如果经中转后更近,那么更新dis
                        dis[i]=dis[tmppos]+dist[tmppos][i];
                    }
                }
             
             
            }
            
            //for_each(load.begin(),load.end(),[](int val){cout<<val<<" ";});
            for(int i=1;i<n;i++)
            {
                ans+=dist[i][i-1];
            }
            cout<<setprecision(3)<<ans<<endl;
        }
    
    
    return 0;
}

上面的dijkstra行不通,两个点间存在最短路径并不代表最后的生成树最小

换prim

load表示已经选取的节点

#include<bits/stdc++.h>
using namespace std;
/*
求把点连起来的最小路径,kruskal?dijkstra?
*/



int main(){
    //kruskal用到并查集
    //dijkstra不用
    int n;
    
        while(cin>>n)
        {
            vector<vector<double>>dist(n,vector<double>(n,0));//存放点i到j的距离
            vector<vector<double>>pos(n,vector<double>(2,0));//存放点的坐标
            
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<2;j++)
                {
                    cin>>pos[i][j];
                }
            }
            
            for(int i=0;i<n;i++)//初始化dist矩阵,i到j的距离
            {
                for(int j=0;j<n;j++)
                {
                    if(i==j){continue;}
                    int dx=pos[i][0]-pos[j][0];
                    int dy=pos[i][1]-pos[j][1];
                    dist[i][j]=sqrt(dx*dx+dy*dy);
                }
            }
            //cout<<setprecision(3)<<dist[1][0];
            
            //初始化dis数组,第一个dis数组以0号坐标点开始
            double ans=0;
            
            vector<int>visted(n,0);
            visted[0]=1;
            vector<double>dis(n,0);
            int tmppos;
            vector<int>load(n,0);
            int k;
            
            for(int i=1;i<n;i++)
            {
                dis[i]=dist[0][i];
            }
            
            for(int t=1;t<n;t++)//dijkstraWA了,换prim
            {    
                double mindis=INT_MAX;
                //min_edge=Max;
                for(int i=0;i<t;i++)//在所有已选取的点中
                {
                    for(int j=0;j<n;j++)//找距离最小且未访问过的边
                    {
                        if(dist[load[i]][j]<mindis&&visted[j]!=1)
                        {
                            mindis=dist[load[i]][j];
                            k=j;
                        }
                    }
                }//寻找最小生成树中节点到其它节点最小的边。
                load[t]=k;//将该节点加入到最小生成树节点集合
                visted[k]=true;
                //cout<<mindis<<" ";
                ans=ans+mindis;//将该边的长度加入到sum中

                
            }
    cout<<setprecision(6)<<ans<<endl;
            //cout<<dist[0][1];
        }
    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值