您的位置:首页 > 其它

HDU 1233 还是畅通工程(最小生成树)

2014-12-31 01:44 323 查看
仔细想想这就是一道最裸的最小生成树题目

这里给出prim和kruscal两种方法计算

当然因为这题目是密集边

所以其实prim算法更加好一点的

prim:

/*
最小生成树,prim算法
*/
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 105;
const int INF = 0x3f3f3f3f;

int k , fa
, minn
, first
, vis
;//vis
表示是否添入以保存的集合

struct Edge{
int y , next , d;
bool operator<(const Edge & m )const{
return d < m.d;
}
}e[N*N];

void add_edge(int x , int y, int d)
{
e[k].y = y , e[k].next = first[x] , e[k].d = d;
first[x] = k++;
}

int prim(int src , int n)
{
memset(minn , 0x3f , sizeof(minn));
memset(vis , 0 , sizeof(vis));
vis[src] = 1;
for(int i = first[src] ; i!=-1 ; i=e[i].next)
{
int v = e[i].y;
if(!vis[v]) minn[v] = min(minn[v] , e[i].d);
}
int ans = 0;
for(int i = 1 ; i<n ; i++)
{
int index = 0 , Min = INF;
for(int j = 1 ; j<=n ; j++)
{
if(minn[j] < Min){
Min = minn[j];
index = j;
}
}
ans += Min;
minn[index] = INF;
vis[index] = 1; //使index不能再被访问
//更新
for(int j = first[index] ; j!=-1 ; j=e[j].next)
{
int v = e[j].y;
if(!vis[v]) minn[v] = min(minn[v] , e[j].d);
}
}
return ans;
}

int main()
{
// freopen("a.in" , "r" , stdin);
int n , m , a , b , d;
while(scanf("%d" , &n) , n)
{
m = n*(n-1) / 2;
for(int i = 1 ; i<=n ; i++) fa[i] = i;

k = 0;
memset(first , -1 , sizeof(first));
for(int i = 0 ; i<m ; i++){
scanf("%d%d%d" , &a , &b , &d);
add_edge(a , b , d);
add_edge(b , a , d);
}

printf("%d\n" , prim(1 , n));
}
return 0;
}


kruscal:

/*
最小生成树,prim算法
*/
#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int N = 105;

int k , fa
;

struct Edge{
int x , y , d;
bool operator<(const Edge & m )const{
return d < m.d;
}
}e[N*N];

void add_edge(int x , int y, int d)
{
e[k].x = x , e[k].y = y , e[k].d = d;
k++;
}

int get_head(int x)
{
while(x != fa[x]) x=fa[x];
return x;
}

bool Union(int x , int y)
{
int fa_x = get_head(x);
int fa_y = get_head(y);
if(fa_x != fa_y){
fa[fa_x] = fa_y;
return true;
}
return false;
}

int main()
{
// freopen("a.in" , "r" , stdin);
int n , m , a , b , d;
while(scanf("%d" , &n) , n)
{
k = 0;
m = n*(n-1) / 2;

for(int i = 1 ; i<=n ; i++) fa[i] = i;

for(int i = 0 ; i<m ; i++){
scanf("%d%d%d" , &a , &b , &d);
add_edge(a , b , d);
}
sort(e , e+k);
int ans = 0;
for(int i = 0 ; i<k ; i++){
if(Union(e[i].x , e[i].y)) ans += e[i].d;
}
printf("%d\n" , ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: