考虑到原来已经有一定的城市已经相连,这里要计算出总共的根节点数目rootNum,方法为寻找每一个节点的父节点,若该节点的父节点与自身相等,则rootNum++;最终只需从可选边中用克鲁斯卡尔算法选择出rootNum-1条边即满足要求。
由于Scanner过于慢,这里读入数据用到了其他人写的内部快速输入类。
ACM—JAVA最快的输入方式
下面附上ac代码
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class Main
{
static class Reader
{
BufferedReader br;
StringTokenizer st;
Reader(InputStream input)
{
br = new BufferedReader(new InputStreamReader(input));
st = null;
}
public String next() throws IOException
{
while(st==null || !st.hasMoreTokens())
{
String str = br.readLine();
if(str==null)
return null;
st = new StringTokenizer(str);
}
return st.nextToken();
}
public int nextInt() throws NumberFormatException, IOException
{
return Integer.parseInt(next());
}
}
static class Edge
{
public int start,end,value;
public String toString()
{
return start+" "+end+" "+value;
}
}
static int T,N,M,K;
static int[] pre;
static Edge[] edge;
static int rootNum;
static int find(int n)
{
if(n==pre[n])
return n;
else
return pre[n] = find(pre[n]);
}
static void initData(Reader in) throws NumberFormatException, IOException
{
N = in.nextInt();
M = in.nextInt();
K = in.nextInt();
pre = new int[N+1];
edge = new Edge[M+1];
rootNum = 0;
for(int i=1;i<=N;i++)
pre[i] = i;
for(int i=1;i<=M;i++)
{
edge[i] = new Edge();
edge[i].start = in.nextInt();
edge[i].end = in.nextInt();
edge[i].value = in.nextInt();
}
while(K-->0)
{
int t = in.nextInt();
int root = find(in.nextInt());
for(int i=1;i<t;i++)
{
int root1 = find(in.nextInt());
if(root!=root1)
pre[root1]=root;
}
}
for(int i=1;i<=N;i++)
if(pre[i]==i)
rootNum++;
}
static void swap(int a,int b)
{
Edge t = edge[a];
edge[a] = edge[b];
edge[b] = t;
}
static int elemSwap(int left,int right)
{
int point = edge[left].value;
int i = left;
int j = right;
while(i<j)
{
while(i<j && edge[j].value>=point)
j--;
while(i<j && edge[i].value<=point)
i++;
swap(i,j);
}
swap(left,j);
return j;
}
static void quickSort(int left,int right)
{
if(left>=right)
return;
if(left<1 || right>M)
return;
int mid = elemSwap(left,right);
quickSort(left,mid-1);
quickSort(mid+1,right);
}
static void showData()
{
quickSort(1,M);
for(int i=1;i<=M;i++)
System.out.println(edge[i]);
for(int i=1;i<=N;i++)
System.out.printf("%3d",pre[i]);
System.out.println();
System.out.println("rootNum="+rootNum);
}
static int Kruskal()
{
int sum = 0;
int cnt = 0;
quickSort(1,M);
for(int i=1;i<=M;i++)
{
if(cnt==rootNum-1)
break;
int roota = find(edge[i].start);
int rootb = find(edge[i].end);
if(roota!=rootb)
{
cnt++;
sum += edge[i].value;
pre[roota] = rootb;
}
}
if(cnt==rootNum-1)
return sum;
else
return -1;
}
public static void main(String[] args) throws NumberFormatException, IOException
{
Reader in = new Reader(System.in);
T = in.nextInt();
while(T-->0)
{
initData(in);
// showData();
System.out.println(Kruskal());
}
}
}