题目链接:(—_—) zZ
题目大意:有n个点, m条边,每条边有一定的花费, n个点是连通的(没有循环)且花费最大
思路:用最小生成树算法就ok了, priem时要判重边
code:prime+堆优化(第一回用,wa了半天)
#include <stdio.h>
#include <string.h>
struct
{
int weight, num;
}dis[1002];
int n = 0, m = 0, ans = 0, total = 0, flag = 0, head[1002], map[1002][1002];
void swap(int a, int b)
{
dis[0] = dis[a];
dis[a] = dis[b];
dis[b] = dis[0];
head[dis[a].num] = a;
head[dis[b].num] = b;
}
void sift(int l)
{
int i = 0, j = 0, x = 0;
x = dis[l].weight;
i = l; j = 2*i;
while(j<=total)
{
if(j<total && dis[j].weight<dis[j+1].weight) j++;
if(x<dis[j].weight)
{
swap(i, j);
i = j;
j = 2*i;
}
else
break;
}
dis[i].weight = x;
}
void heap_sort()
{
int i = 0;
for(i = n/2; i>0; i--)
sift(i);
}
void prime()
{
int i = 0, u = 0, p = 0;
for(i = 2; i<=n; i++)
{
dis[++total].weight = map[1][i];
head[i] = total;//记录顶点i在dis中的位置
dis[total].num = i;//记录当前为顶点i
}
head[1] = total;
while(total)
{
heap_sort();
u = dis[1].num;
ans += dis[1].weight;
if(dis[1].weight == -1)//判断连通不
flag = 1;
swap(1, total);
total--;
for(i = 2; i<=n; i++)
{
p = head[i];//通过当前点更新其他点
if(p<=total && dis[p].weight<map[u][i])
dis[p].weight = map[u][i];
}
}
}
int main()
{
int i = 0, u = 0, v = 0, cost = 0, count = 0;
while(scanf("%d %d", &n, &m) != EOF)
{
memset(map, -1, sizeof(map));
for(i = 0; i<m; i++)
{
scanf("%d %d %d", &u, &v, &cost);
if(map[u][v] == -1 || map[u][v]<cost)
map[u][v] = map[v][u] = cost;
}
ans = flag = 0;
prime();
if(!flag)
printf("%d\n", ans);
else
printf("-1\n");
}
return 0;
}
code: prime
#include <stdio.h>
#include <string.h>
int n = 0, m = 0, map[1002][1002], used[1002], dis[1002];
void prime()
{
int i = 0, j = 0, k = 0, min = 0;
memset(used, 0, sizeof(used));
for(i = 1; i<=n; i++)
dis[i] = map[1][i];
used[1] = 1;
for(i = 1; i<=n; i++)
{
min = 0;
for(j = 1; j<=n; j++)
if(!used[j] && min<dis[j])
{
min = dis[j];
k = j;
}
used[k] = 1;
for(j = 1; j<=n; j++)
{
if(!used[j] && map[k][j] != -1 && dis[j]<map[k][j])
dis[j] = map[k][j];
}
}
}
int main()
{
int i = 0, j = 0, u = 0, v = 0, cost = 0, ans = 0, count = 0;
while(scanf("%d %d", &n, &m) != EOF)
{
memset(map, -1, sizeof(map));
for(i = 0; i<m; i++)
{
scanf("%d %d %d", &u, &v, &cost);
if(map[u][v] == -1 || map[u][v]<cost)
map[u][v] = map[v][u] = cost;
}
prime();
for(i = 1; i<=n; i++)
if(used[i])
count++;
if(count == n)
{
for(i = 2; i<=n; i++)
ans += dis[i];
printf("%d\n", ans);
}
else
printf("-1\n");
}
return 0;
}
code:kruskal
#include <stdio.h>
#include <stdlib.h>
struct node
{
int u, v, cost;
} edge[20002];
int n = 0, m = 0, count = 0, sum = 0, father[1002], rank[1002];
int cmp(void const *a, void const *b)
{
return -((*(struct node *)a).cost-(*(struct node *)b).cost);
}
int find(int x)
{
if(father[x] != x)
father[x] = find(father[x]);
return father[x];
}
void Union(int x, int y)
{
if(rank[x]>rank[y])
father[y] = x;
else
{
if(rank[x] == rank[y])
rank[y]++;
father[x] = y;
}
}
void kruskal()
{
int i = 0, fx = 0, fy = 0;
sum = 0;
for(i = 0; i<m; i++)
{
fx = find(edge[i].u); fy = find(edge[i].v);
if(fx != fy)
{
Union(fx, fy);
sum += edge[i].cost;
count++;
}
}
}
int main()
{
int i = 0;
while(scanf("%d %d", &n, &m) != EOF)
{
for(i = 1; i<=n; i++)
{
rank[i] = 0;
father[i] = i;
}
for(i = 0; i<m; i++)
scanf("%d %d %d", &edge[i].u, &edge[i].v, &edge[i].cost);
qsort(edge, m, sizeof(edge[0]), cmp);
kruskal();
if(count == n-1)
printf("%d\n", sum);
else
printf("-1\n");
}
return 0;
}