题目链接:Click
题意:有n台电脑,现在给你每两台电脑之间连接所需要的权值,如果权值为0,代表不能连接,问如果把所有电脑全部连接起来的最小花费的连接方式。
思路:这道题目看上去就是一道最小生成树的题,然后我就找出kruskal的模板敲上去,结果超时了。。一般这种时候我就会先放下,和队友看其他题目,最后一个小时的时候,我回来看这道题,发现以前貌似见到过这道题,好像用到了并查集。然后就开始重新搞。。。关键还是英语不好,没读懂后面有一句输出按字典序排,结果又错了,最后在队友的帮助下成功AC
附上最终代码:
#include <stdio.h>
#include <algorithm>
#include <iostream>
using namespace std;
#define MAXN 120
int N, cnt;
int fid[MAXN];
struct node
{
int u, v, w;
} edge[MAXN*60];
struct node2
{
int a, b;
} ans[MAXN];
int find(int x)
{
int t = fid[x];
while(t != fid[t])
{
t=fid[t];
}
return t;
}
void merge(int x, int y)
{
fid[x]=y;
}
bool cmp(node a, node b)
{
if(a.w != b.w)return a.w < b.w;
return a.u < b.u;
}
bool cmp2(node2 s1, node2 s2)
{
if(s1.a != s2.a)return s1.a < s2.a;
return s1.b < s2.b;
}
int kruskal()
{
int flag = 0;
sort(edge, edge + cnt, cmp);
for(int i = 0; i < cnt; i++)
{
int x = find(edge[i].u);
int y = find(edge[i].v);
if(x!=y)
{
merge(x,y);
ans[flag].a = edge[i].u;
ans[flag].b = edge[i].v;
flag++;
}
}
return flag;
}
int main(int argc, char *argv[])
{
int T, v, tag;
scanf("%d", &T);
while(T--)
{
cnt = 0;
scanf("%d", &N);
for(int i = 1; i <= N; i++)
{
fid[i] = i;
}
for(int i = 1; i <= N; i++)
{
for(int j = 1; j <= N; j++)
{
scanf("%d", &v);
if(i < j && v > 0)
{
edge[cnt].u = i;
edge[cnt].v = j;
edge[cnt].w = v;
cnt++;
}
}
}
tag = kruskal();
if(tag != N-1)
{
printf("-1\n");
}
else
{
sort(ans, ans + tag, cmp2);
for(int i = 0; i < tag - 1; i++)
printf("%d %d ",ans[i].a, ans[i].b);
printf("%d %d\n", ans[tag-1].a, ans[tag-1].b);
}
}
return 0;
}