您的位置:首页 > 其它

poj 2485 简单的最小生…

2013-12-14 20:03 447 查看
题目意思:要你求一个生成树 , 使这个生成树(不一定是最小生成树)中边权最大值最小 , 并输出该值。

这个题目我一开始用的是kruskal算法 , 先对边进行排序 , 但后面犯了一个错误 , 当判断是否存在生成树时 ,
我判断的是前面的边是否包含所有顶点(没有发现 , 有可能这些点不是在通一个连通图中) , 应该用并查集 。

其实最大值最小就是最小生成树中的最大值 , 这个性质的证明可以用kruskal算法来证明:

  1、对边排序后 , 我们取前n-1条边 , 如果这n-1条边 , 构成了最小生成树 ,
那么该值就是它们之间的最大值 。

  2、如果不能构成生成树 , 那么继续加入下一条边(除开已取的边之外 , 取剩下边的最小值) ,
因为前面那些边不能构成生成树 , 那么如果加入这条边之后 , 可以构成生成树 , 则这条边肯定在该生成树中 ,
并且这条边的权值就是我们要求的值 。

  3、如果加入该边后还不能构成最小生成树 , 那么重复步骤2 
, 直到可以形成生成树为止。

代码:

#include

#include

#include

using namespace std;

const int MAXN = 550 ;

int grap[MAXN][MAXN] , u[630000] , v[630000] , d[630000] ;

int done[630000] , n , f[MAXN];

bool cmp(int i , int j)

{

    return d[i]
< d[j];

}

int find(int x)

{

    int u =
x;

    while(x !=
f[x])

    {

   
    x =
f[x];

    }

    while(u !=
x)

    {

   
    int p =
f[u];

   
    f[u] =
x;

   
    u = p;

    }

    return
x;

}

int main()

{

    int t;

    scanf("%d" ,
&t);

   
while(t--)

    {

   
    int i ,
j;

   
   
cin>>n;

   
    for(i = 1; i
<= n; i++)

   
    {

   
   
    for(j = 1; j
<= n; j++)

   
   
   
    scanf("%d" ,
&grap[i][j]);

   
   
    f[i] =
i;

   
    }

   
    int x =
0;

   
    for(i = 1; i
<= n; i++)

   
    {

   
   
    for(j = i+1;
j <= n; j++)

   
   
    {

   
   
   
    u[x] =
i;  v[x] = j;

   
   
   
    d[x] =
grap[i][j];

   
   
   
    done[x] =
x;

   
   
   
    x +=
1;

   
   
    }

   
   
   

   
    }

   
    int c , g ,
h;

   
    sort(done ,
done+x , cmp);

   
   
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: