Kruskal最小生成树,边排序的时候同时要将点排序,因为结果要求按字典序输出。注意全连通的条件是边数刚好等于顶点数减一,刚开始想错了,WA了几次,TAT,图论基础不行啊
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Computer
{
int index;
struct Computer *parent;
int rank;
};
struct Connect
{
struct Computer *u;
struct Computer *v;
int cost;
};
static struct Computer *make_set(int index)
{
struct Computer *v = malloc(sizeof(struct Computer));
v->index = index;
v->parent = v;
v->rank = 0;
return v;
}
static struct Computer *find_set(struct Computer *v)
{
if (v->parent != v)
v->parent = find_set(v->parent);
return v->parent;
}
static void link(struct Computer *u, struct Computer *v)
{
if (u->rank > v->rank)
v->parent = u;
else
{
u->parent = v;
if (u->rank == v->rank)
v->rank++;
}
}
static void union_set(struct Computer *u, struct Computer *v)
{
link(find_set(u), find_set(v));
}
static int cmp(const void *p1, const void *p2)
{
struct Connect *c1 = (struct Connect*) p1;
struct Connect *c2 = (struct Connect*) p2;
if (c1->cost != c2->cost)
return c1->cost - c2->cost;
else if (c1->u->index != c2->u->index)
return c1->u->index - c2->u->index;
else
return c1->v->index - c2->v->index;
}
int main()
{
int t, i, j, n, map[100][100];
scanf("%d", &t);
struct Computer **array = malloc(100 * sizeof(struct Computer*));
struct Connect *net = malloc(5000 * sizeof(struct Connect));
for (i = 0; i < 100; i++)
array[i] = make_set(i);
while (t--)
{
scanf("%d", &n);
for (i = 0; i < n; i++)
{
array[i]->parent = array[i];
array[i]->rank = 0;
}
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
scanf("%d", &map[i][j]);
int total = 0, res = 0;
for (i = 0; i < n; i++)
for (j = i + 1; j < n; j++)
{
if (!map[i][j])
continue;
net[total].u = array[i];
net[total].v = array[j];
net[total++].cost = map[i][j];
}
qsort(net, total, sizeof(struct Connect), cmp);
for (i = 0; i < total; i++)
{
struct Computer *c1 = find_set(net[i].u);
struct Computer *c2 = find_set(net[i].v);
if (c1 != c2)
{
union_set(c1, c2);
net[i].cost = 0;
res++;
}
}
qsort(net, total, sizeof(struct Connect), cmp);
if (res == n - 1)
{
for (i = 0; i < res; i++)
printf(i ? " %d %d" : "%d %d", net[i].u->index + 1,
net[i].v->index + 1);
putchar('\n');
}
else
puts("-1");
}
for (i = 0; i < n; i++)
free(array[i]);
free(net);
free(array);
return 0;
}