题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6187
Problem Description Long times ago, there are beautiful historic walls in the city. These walls divide the city into many parts of area.
Input There are several test cases.
Output For each test case outout one line with 2 integers sperate by a space, indicate how many walls the king should destroy at least to achieve his goal, and the minimal cost under this condition.
Sample Input 4 4 -1 -1 -1 1 1 1 1 -1 1 2 1 2 3 2 3 4 1 4 1 2
Sample Output 1 1
|
题意:有几个城楼和连接城楼的城墙,先求要使国王城堡能够随意的到达呵任何城楼。
那么城楼相互之间一定没有环。
我们知道,如果一个平面上一个点可以到达平面的任何地方,这个平面是一定没有封闭的区域的。
什么叫没有封闭的区域?就是没有环。
既然没有环,又需要减少最少的边,那么就是要变成一堆树啦(森林)。
而我们在减少最少的边的情况下,又需要减掉的边的权值和最小。
那么就是留下的树上的边的权值和最大,不是最大生成树还是什么?
此题的坐标完全无用。。。
步骤思路:给定了墙的代价及墙两端的城楼,就相当于给定了每个点及相连的边,在这个图内找最大的生成树。。。
每次找最长的边,然后为防止找到的边围成环,需判断这条边的两个端点是否属于同一棵数,需要进行并查集操作
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
struct edge{
int from, to, cost;
}G[200005];
int n,m;
bool cmp(edge a, edge b){ return a.cost>b.cost; }
int root[100005];
int rootof(int x){
return root[x]=root[x]==x?x:rootof(root[x]);
}
bool merge(int a, int b){
int ra = rootof(a), rb = rootof(b);
if(ra==rb)return false; // already merged.
else root[ra]=rb;
return true;
}
int main() {
while(scanf("%d%d",&n,&m)!=EOF){
int x,y;
for(int i=1;i<=n;i++){
scanf("%d%d",&x,&y);
root[i]=i;//起初定义每个点的根是它本身
}
long long res = 0;
int cnt = 0;
for(int i=0;i<m;i++){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
G[i].from=a,G[i].to=b,G[i].cost=c;
res+=c;
}
sort(G,G+m,cmp);
for(int i=0;i<m;i++){
if(merge(G[i].from,G[i].to)){
res-=G[i].cost;
cnt++;
}
}
printf("%d %lld\n",m-cnt,res);
}
return 0;
}