2011-05-14 20:47:00Morris
a129. 最小生成樹
給你一個加權的無向圖(weighted undirected graph),請問這個圖的最小生成樹(minimum spanning tree)的權重和為多少?
輸入說明
:
輸入可能包含多筆測試資料,以EOF作為結束。
每筆測試資料的第一列有兩個整數n,m(1<=n<=100,000;0<=m<=200,000),代表該圖的點數和邊數。
頂點的編號從0到n-1。
接下來有m列,每列用三個整數i,j,c(0<=i,j<n;c為int可儲存的非負整數)描述一條邊,i,j為兩個端點的編號,c為其權重。
輸出說明
:
對於每筆測試資料,請輸出最小生成樹的權重和。如果圖不連通,請輸出-1。
範例輸入 :
3 3 1 2 5 2 3 5 3 1 10 4 2 1 2 5 2 3 5
範例輸出 :
10 -1
提示
:
overflow..?
出處
:
(管理:shik)
作法: 并查集
/**********************************************************************************/
/* Problem: a129 "最小生成樹" from */
/* Language: C */
/* Result: AC (876ms, 10432KB) on ZeroJudge */
/* Author: morris1028 at 2011-05-14 20:44:26 */
/**********************************************************************************/
#include<stdio.h>
#include<stdlib.h>
int Parent[100001], Rank[100001];
int a, N, M;
void MakeSet(int N) {
for(a=0;a<=N;a++)
Parent[a] = a, Rank[a] = 1;
}
int FindSet(int x) {
if(x!=Parent[x])
Parent[x] = FindSet(Parent[x]);
return Parent[x];
}
void Link(int x, int y) {
if(Rank[x]>Rank[y])
Parent[y] = x, Rank[x] += Rank[y];
else
Parent[x] = y, Rank[y] += Rank[x];
}
int Union(int x, int y) {
x = FindSet(x), y = FindSet(y);
if(x != y) {
Link(x, y);
return 1;
}
return 0;
}
int Input() {
char cha;
unsigned int x=0;
while(cha=getchar())
if(cha!=' '&&cha!='\n' || cha==EOF) break;
if(cha==-1) return -1;
x=cha-48;
while(cha=getchar()) {
if(cha==' '||cha=='\n') break;
x=x*10+cha-48;
}
return x;
}
struct Axis{
int x, y, s;
}Data[400001], X[400001];
void Merge(int, int, int);
void MergeSort(int, int);
main() {
int T, a, flag;
long long Ans;
while(scanf("%d %d",&N, &M) == 2) {
for(a=0;a<M;a++) {
Data[a].x = Input(), Data[a].y = Input(), Data[a].s = Input();
Data[M+a].x = Data[a].x,
Data[M+a].y = Data[a].y,
Data[M+a].s = Data[a].s;
}
M *= 2;
MergeSort(0, M-1), MakeSet(N), Ans = 0, flag = 0;
for(a=0;a<M && flag < N;a++)
if(Union (Data[a].x, Data[a].y) == 1) {
Ans += Data[a].s, flag ++;
}
printf("%lld\n",(flag == N-1)? Ans : -1);
}
return 0;
}
void MergeSort(int l, int h) {
if(l < h) {
int m=(l+h)/2;
MergeSort(l ,m);
MergeSort(m+1,h);
Merge(l,m,h);
}
}
void Merge(int l, int m, int h) {
int In1=l, In2=m+1;
int a, b, Top=0;
while(In1<=m && In2<=h)
if((Data[In1].s < Data[In2].s))
X[Top++]=Data[In1++];
else X[Top++]=Data[In2++];
while(In1<=m) X[Top++]=Data[In1++];
while(In2<=h) X[Top++]=Data[In2++];
for(a=0,b=l;a<Top;a++,b++)
Data[b]=X[a];
}
作法: 并查集
/**********************************************************************************/
/* Problem: a129 "最小生成樹" from */
/* Language: C */
/* Result: AC (876ms, 10432KB) on ZeroJudge */
/* Author: morris1028 at 2011-05-14 20:44:26 */
/**********************************************************************************/
#include<stdio.h>
#include<stdlib.h>
int Parent[100001], Rank[100001];
int a, N, M;
void MakeSet(int N) {
for(a=0;a<=N;a++)
Parent[a] = a, Rank[a] = 1;
}
int FindSet(int x) {
if(x!=Parent[x])
Parent[x] = FindSet(Parent[x]);
return Parent[x];
}
void Link(int x, int y) {
if(Rank[x]>Rank[y])
Parent[y] = x, Rank[x] += Rank[y];
else
Parent[x] = y, Rank[y] += Rank[x];
}
int Union(int x, int y) {
x = FindSet(x), y = FindSet(y);
if(x != y) {
Link(x, y);
return 1;
}
return 0;
}
int Input() {
char cha;
unsigned int x=0;
while(cha=getchar())
if(cha!=' '&&cha!='\n' || cha==EOF) break;
if(cha==-1) return -1;
x=cha-48;
while(cha=getchar()) {
if(cha==' '||cha=='\n') break;
x=x*10+cha-48;
}
return x;
}
struct Axis{
int x, y, s;
}Data[400001], X[400001];
void Merge(int, int, int);
void MergeSort(int, int);
main() {
int T, a, flag;
long long Ans;
while(scanf("%d %d",&N, &M) == 2) {
for(a=0;a<M;a++) {
Data[a].x = Input(), Data[a].y = Input(), Data[a].s = Input();
Data[M+a].x = Data[a].x,
Data[M+a].y = Data[a].y,
Data[M+a].s = Data[a].s;
}
M *= 2;
MergeSort(0, M-1), MakeSet(N), Ans = 0, flag = 0;
for(a=0;a<M && flag < N;a++)
if(Union (Data[a].x, Data[a].y) == 1) {
Ans += Data[a].s, flag ++;
}
printf("%lld\n",(flag == N-1)? Ans : -1);
}
return 0;
}
void MergeSort(int l, int h) {
if(l < h) {
int m=(l+h)/2;
MergeSort(l ,m);
MergeSort(m+1,h);
Merge(l,m,h);
}
}
void Merge(int l, int m, int h) {
int In1=l, In2=m+1;
int a, b, Top=0;
while(In1<=m && In2<=h)
if((Data[In1].s < Data[In2].s))
X[Top++]=Data[In1++];
else X[Top++]=Data[In2++];
while(In1<=m) X[Top++]=Data[In1++];
while(In2<=h) X[Top++]=Data[In2++];
for(a=0,b=l;a<Top;a++,b++)
Data[b]=X[a];
}
上一篇:d788. 排名順序
(悄悄話)
2011-11-25 22:42:08
您好,我剛剛發的那一大串程式碼的主人,我突然想到:我如果用悄悄話打,我就看不到東西了,可以請您回覆在這篇嗎?