[JOYOI1307] 联络员
题目限制
时间限制 | 内存限制 | 评测方式 | 题目来源 |
1000ms | 131072KiB | 标准比较器 | Local |
题目描述
Tyvj已经一岁了,网站也由最初的几个用户增加到了上万个用户,随着Tyvj网站的逐步壮大,管理员的数目也越来越多,现在你身为Tyvj管理层的联络员,希望你找到一些通信渠道,使得管理员两两都可以联络(直接或者是间接都可以)。Tyvj是一个公益性的网站,没有过多的利润,所以你要尽可能的使费用少才可以。
目前你已经知道,Tyvj的通信渠道分为两大类,一类是必选通信渠道,无论价格多少,你都需要把所有的都选择上;还有一类是选择性的通信渠道,你可以从中挑选一些作为最终管理员联络的通信渠道。数据保证给出的通行渠道可以让所有的管理员联通。
输入格式
第一行n,m表示Tyvj一共有n个管理员,有m个通信渠道
第二行到m+1行,每行四个非负整数,p,u,v,w 当p=1时,表示这个通信渠道为必选通信渠道;当p=2时,表示这个通信渠道为选择性通信渠道;u,v,w表示本条信息描述的是u,v管理员之间的通信渠道,u可以收到v的信息,v也可以收到u的信息,w表示费用。
输出格式
最小的通信费用
提示
样例解释:
1-2-3-4-1存在四个必选渠道,形成一个环,互相可以到达。需要让所有管理员联通,需要联通2和5号管理员,选择费用为5的渠道,所以总的费用为9
注意:
U,v之间可能存在多条通信渠道,你的程序应该累加所有u,v之间的必选通行渠道
数据范围:
对于30%的数据,n<=10 m<=100
对于50%的数据, n<=200 m<=1000
对于100%的数据,n<=2000 m<=10000
样例数据
输入样例 #1 | 输出样例 #1 |
---|---|
5 6 1 1 2 1 1 2 3 1 1 3 4 1 1 4 1 1 2 2 5 10 2 2 5 5 |
9 |
提交地址 : JOYOI1307
题解:
水题;
考试考过;
Code:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 int n, m; 8 9 struct edge 10 { 11 int x, y, val; 12 bool operator < (edge a){return val < a.val;} 13 }ed[20010]; 14 int cnt; 15 inline void add(int x, int y, int z) 16 { 17 cnt++; 18 ed[cnt] = (edge){x, y, z}; 19 } 20 int bi[20010], top; 21 int fa[2010]; 22 inline int Find(int x){return x == fa[x] ? x : fa[x] = Find(fa[x]);} 23 int ans = 0; 24 int tot; 25 26 int main() 27 { 28 cin >> n >> m; 29 for (register int i = 1 ; i <= m ; i ++) 30 { 31 int p, x, y, z; 32 scanf("%d%d%d%d", &p, &x,&y, &z); 33 add(x, y, z); 34 if (p == 1) bi[++top] = cnt; 35 } 36 37 for (register int i = 1 ; i <= n ; i ++) fa[i] = i; 38 for (register int i = 1 ; i <= top ; i ++) 39 { 40 int fx = Find(ed[bi[i]].x) , fy = Find(ed[bi[i]].y); 41 if (fx != fy) tot++; 42 ans += ed[bi[i]].val; 43 fa[fx] = fy; 44 } 45 sort(ed + 1, ed + 1 + cnt); 46 for (register int i = 1 ; i <= cnt ; i ++) 47 { 48 int fx = Find(ed[i].x), fy = Find(ed[i].y); 49 if (fx == fy) continue; 50 fa[fx] = fy; 51 ans += ed[i].val; 52 tot++; 53 if (tot == n - 1) break; 54 } 55 cout << ans << endl; 56 return 0; 57 }