本题数据量有点大,暴力的结果是TLE。
读入用了scanf没用cin,不知道会不会TLE。
使用三个一维数组代替二维数组存储边,降低时间复杂度,如果细看的话也可以知道降低了内存消耗:m <= 25000, n * n <= 250000。
还有就是读入数据需要细心一点,基本就可以了。
#include<iostream>
#include<cstring>
using namespace std;
const int NN = 500 + 5, NM = 25000 + 5, INF = 99999999;
int f[NN], c1[NM], c2[NM], c3[NM];//f[NN]记录每个顶点的根节点,c三个一维数组代替二维数组存储边以降低时间复杂度
int find(int x)
{//寻找根节点
if (x == f[x]) return x;
f[x] = find(f[x]);
return f[x];
}
int mer(int x, int y)
{//x和y所在的两个集合合并
x = find(x);
y = find(y);
if (x != y)
f[x] = y;
return 1;
}
int main()
{
int T, n, m, k, t, x, y, sum;//T为测试数据组数,sum记录最小花费,其他对应题目数据
cin >> T;
while (T--)
{
sum = 0;
scanf("%d %d %d", &n, &m, &k);
for (int i = 1; i <= n; i++)
f[i] = i;//集合初始化
for (int i = 1; i <= m; i++)
scanf("%d %d %d", &c1[i], &c2[i], &c3[i]);//用三个一维数组进行存储,下面的计算降低时间复杂度
for (int i = 0; i < k; i++)//输入细心一点就可以了
{
scanf("%d %d", &t, &x);
while (t != 1)
{
scanf("%d", &y);
mer(x, y);
x = y;
t--;
}
}
while (1)
{
int min0 = INF, flag = 1;
//如果用二维数组存储数据,使用Prime算法要用到双重for,加上while,时间复杂度是O(n^3),本题数据量大,会TLE
for(int i = 1; i <= m; i++)
if (min0 > c3[i] && find(c1[i]) != find(c2[i]) )//如果是if(find(c1[i]) != find(c2[i]) && min0 > c3[i]),先进行find会TLE
{
min0 = c3[i];
x = c1[i];
y = c2[i];
flag = 0;
}
if (flag) break;
sum += min0;
mer(x, y);
}
int p = 1;
for(int i = 2; i <= n; i++)//判断是否全连通
if (find(i - 1) != find(i))//若并非全连通,必定存在相邻不同的根节点
{
p = 0;
break;
}
if (p)
cout << sum << endl;
else
cout << "-1" << endl;
}
return 0;
}