题意:
给出N个点,若干边的带权无向图,然后若干个点已经相连了,求使得整个图联通的最小代价。
解法:
这题一般做法是缩点+最小生成树,但是由于这题的特殊性,可以不用显式的缩点,用并查集将已经联通的点合并后直接使用kustral算法构造最小生成树,至于判断图是否联通,一遍DFS判断点数是否相等即可。
附带吗
1 import java.util.*;
2 import java.io.*;
3 public class Main {
4
5 /**
6 * @param args
7 */
8 static int n=0,m=0,k=0;
9 static int pre[]=new int[501];
10 static int buffer[]=new int[501];
11 static int g[]=new int[501],nxt[]=new int[50001],v[]=new int[50001],c=0;
12 static boolean used[]=new boolean[501];
13 static class edge implements Comparable<edge>
14 {
15 int a,b,v;
16 public int compareTo(edge pos)
17 {
18 return v-pos.v;
19 }
20 }
21 static edge data[]=new edge[25001];
22 static int find(int pos)
23 {
24 if(pre[pos]==pos) return pos;
25 else
26 {
27 pre[pos]=find(pre[pos]);
28 return pre[pos];
29 }
30 }
31 static void insert(int s,int e)
32 {
33 v[c]=e;
34 nxt[c]=g[s];
35 g[s]=c++;
36 }
37 static void dfs(int pos)
38 {
39 if(used[pos]) return;
40 used[pos]=true;
41 for(int p=g[pos];p!=-1;p=nxt[p])
42 dfs(v[p]);
43 }
44 public static void main(String[] args) throws IOException{
45 StreamTokenizer in=new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in)));
46 in.nextToken();
47 int test=(int)in.nval;
48 for(int i=0;i<data.length;i++)
49 data[i]=new edge();
50 while((test--)!=0)
51 {
52
53 in.nextToken();
54 n=(int)in.nval;
55 in.nextToken();
56 m=(int)in.nval;
57 in.nextToken();
58 k=(int)in.nval;
59 for(int i=0;i<m;i++)
60 {
61 in.nextToken();
62 data[i].a=(int)in.nval;
63 in.nextToken();
64 data[i].b=(int)in.nval;
65 in.nextToken();
66 data[i].v=(int)in.nval;
67 }
68 for(int i=1;i<=n;i++)
69 {
70 pre[i]=i;
71 g[i]=-1;
72 }
73 for(int i=0;i<k;i++)
74 {
75 in.nextToken();
76 int t=(int)in.nval;
77 for(int j=0;j<t;j++)
78 {
79 in.nextToken();
80 buffer[j]=(int)in.nval;
81 }
82 for(int j=1;j<t;j++)
83 pre[find(buffer[0])]=find(buffer[j]);
84 }
85 int total=0;
86 Arrays.sort(data, 0, m);
87 c=0;
88 for(int i=0;i<m;i++)
89 {
90 insert(find(data[i].a),find(data[i].b));
91 insert(find(data[i].b),find(data[i].a));
92
93 }
94
95 Arrays.fill(used,false);
96 int sum=0;
97 for(int i=1;i<=n;i++)
98 used[find(i)]=true;
99 for(int i=1;i<=n;i++)
100 if(used[i]) sum++;
101 Arrays.fill(used,false);
102 dfs(find(1));
103 for(int i=1;i<=n;i++)
104 if(used[i]) sum--;
105 if(sum!=0)
106 {
107 System.out.println(-1);
108 continue;
109 }
110
111 for(int i=0;i<m;i++)
112 if(find(data[i].a)!=find(data[i].b))
113 {
114 pre[find(data[i].a)]=data[i].b;
115 total+=data[i].v;
116 }
117 System.out.println(total);
118 }
119
120 }
121
122 }
123