[NOIP模擬][最大生成森林]拆牆
阿新 • • 發佈:2019-02-13
題目描述:
地主的傻兒子豆豆家很大很大,由很多個區域組成。其中有不少封閉的區域,豆豆覺得很不爽於是決定拆牆,把家打通使得他可以訪問到每一個區域(包括家外面無限大的區域)。我們用 N 個端點和 M 條邊來描述豆豆的家。第 i 個端點的座標為(xi,yi),第 i 條邊連線端點 Ai 和 Bi,拆除所需要花費的力氣為 Ci 。保證所有邊只在端點相交,也就是這是一個平面圖,也沒有重邊和自環。
現在豆豆想知道他最少一共需要花費多少力氣?(拆牆數最少的前提下)
輸入格式:
第一行一個整數 T 表示資料組數。
每組資料第一行兩個整數 N,M 。
接下來 N 行每行兩個整數
接下來 M 行每行三個整數 i
輸出格式:
每組資料輸出兩個整數表示最少拆除的牆的數量和拆牆最少需要多少的力氣。注意所有牆可能不互相連通。
樣例輸入:
1
4 4
-1 -1
-1 1
1 1
1 -1
1 2 1
2 3 2
3 4 1
4 1 2
樣例輸出:
1 1
資料範圍:
對於 30% 的資料,
對於 70% 的資料,
對於 100% 的資料,
題目分析:
因為題目說了保證所有邊只在端點相交,是一個平面圖,也沒有重邊和自環。所以這道題座標是沒有用的
PS:最大生成森林做法和最小生成樹是一樣的,只是排序是從大到小。
附程式碼:
Kruskal求解:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdlib>
#include<cstdio>
#include<ctime>
#include<cmath>
#include<cctype>
#include<iomanip>
#include<algorithm>
using namespace std;
const int N=1e5+10;
const int M=2e5+10;
int n,m,x,y,fa[N],fta,ftb,t,cnt,ans;
struct node{
int x;
int y;
int w;
}wall[M];
bool comp(const node &a,const node &b)
{
return a.w>b.w;
}
int getfa(int x)
{
if(fa[x]==x) return x;
return fa[x]=getfa(fa[x]);
}
int readint()
{
char ch;int i=0,f=1;
for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar());
if(ch=='-') {ch=getchar();f=-1;}
for(;ch>='0'&&ch<='9';ch=getchar()) i=(i<<3)+(i<<1)+ch-'0';
return i*f;
}
int main()
{
//freopen("wall.in","r",stdin);
//freopen("wall.out","w",stdout);
t=readint();
while(t--)
{
ans=0;
n=readint();m=readint();
for(int i=1;i<=n;i++) x=readint(),y=readint();
for(int i=1;i<=m;i++)
{
wall[i].x=readint();
wall[i].y=readint();
wall[i].w=readint();
ans+=wall[i].w;
}
cnt=m;
for(int i=1;i<=n;i++) fa[i]=i;
sort(wall+1,wall+m+1,comp);
for(int i=1;i<=m;i++)
{
fta=getfa(wall[i].x);
ftb=getfa(wall[i].y);
if(fta!=ftb)
{
fa[fta]=ftb;
ans-=wall[i].w;
cnt--;
}
}
printf("%d %d\n",cnt,ans);
}
return 0;
}