最小生成树模板

给出两个点的距离,问你可以不可以由这些点组成一棵树,我们首先构造一个最小生成树,然后比较各各点之间的距离是否与题目给出的距离相等,可以用dfs搜索整张图的每两个点之间的距离.下面给的做法非dfs做的,用一个数组f[][],记录x,y两点之间的距离,算距离的时候是通过目前点的前驱找,也就是说需要一个数组记录前驱,这样就可以不用dfs了,

#include <iostream>  
#include <cstdio>  
#include <cstring>  
#include <algorithm>  
using namespace std;  
const int maxn = 2010;  
const int INF = 0x3f3f3f3f;  
int graph[maxn][maxn];  
int prior[maxn];  
int visit[maxn];  
int dis[maxn];  
int f[maxn][maxn];  
int n;  
bool check()  
{  
    for(int i = 0; i < n; i++)  
    {  
        dis[i] = INF;  
        if(graph[i][i] != 0) return false;  
        for(int j = i+1 ; j < n; j++)  
        {  
            if(graph[i][j] != graph[j][i] || graph[i][j] == 0) return false;  
        }  
    }  
  
    memset(visit,0,sizeof(visit));  
    memset(prior,-1,sizeof(prior));  
    memset(f,0,sizeof(f));  
    int cent = n;  
    dis[0]=0;  
    while(cent--)//循环n次是因为要初始化  
    {  
  
        int min = -1;  
        for(int i = 0; i < n; i++)  
        {  
            if(!visit[i] && (min == -1 || dis[i] < dis[min]))  
            {  
                min = i;  
            }  
        }  
        for(int i = 0; i < n; i++)//在prim算法里面增加这层循环里面的内容算距离  
        {  
            if(visit[i])//必须是已经访问过的点,才能算距离  
            {  
                f[i][min] = f[min][i] = f[i][prior[min]] + dis[min];  
            }  
        }  
        visit[min] = true;  
        for(int i = 0; i < n; i++)  
        {  
            if(dis[i] > graph[min][i] )  
            {  
                dis[i] = graph[min][i];  
                prior[i] = min;//记录前驱  
            }  
        }  
    }  
  
    for(int i = 0; i < n; i++)  
    {  
        for(int j = 0 ; j < n; j++)  
        {  
            if(f[i][j] != graph[i][j])  
            {  
                return false;  
            }  
        }  
    }  
      return true;  
}  
int main()  
{  
#ifdef xxz  
    freopen("in","r",stdin);  
#endif // xxz  
    while(cin>>n)  
    {  
        for(int i = 0; i < n; i++)  
            for(int j = 0; j < n; j++)  
            {  
                cin>>graph[i][j];  
            }  
  
        if(check()) cout<<"YES"<<endl;  
        else cout<<"NO"<<endl;  
    }  
    return 0;  
}  


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值