必選邊之最小聯絡

題面
Description

N個點,M條邊,其中K條邊必選,求所有點點之間都有可達的最小代價。數據保證有解。

Input

第一行兩個整數n,m。
第二行到m+1行,每行四個非負整數,p,u,v,w 當p=1時,表示必選邊;當p=2時,表示可選邊;u,v,w一條無向邊端點爲u和v,權值爲w。

Output

最小費用。

Sample Input
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

Sample Output
9

HINT

數據範圍:

對於30%的數據,n<=10 m<=100

對於50%的數據, n<=200 m<=1000

對於100%的數據,n<=2000 m<=10000

題目分析
題目的意思是很好理解的,無非是在取了特定邊的情況下,求最小連通圖——最小生成樹

實現方面便是,先將特定的邊加到圖中並且對邊進行處理,之後把剩餘的再整理一下,去算最小生成樹

代碼

#include <bits/stdc++.h>
using namespace std;

struct node
{
	int u;
	int v;
	int w;
}e[500009];

long long f[500009];    
long long n,m;
long long ans,cnt = 0;

bool cmp(node x,node y)
{
	return x.w < y.w;
}

int find(int x)              //尋根
{
	if (f[x] == x) return x;
	f[x] = find(f[x]);
	return f[x];
}

long long kruskal()
{
	long long sum = 0;
	
	for (int i = 1; i <= cnt; i++)
		if (find(e[i].u) != find(e[i].v))                //對環的判斷
			f[find(e[i].v)] = find(e[i].u),
			sum += e[i].w;
		
	return sum;
}

int main()
{
	long long p,u1,v1,w1;
	
	cin>>n>>m;
	for (int i = 1; i <= n; i++) f[i] = i;
	for (int i = 1; i <= m; i++)
		{
			scanf("%d%d%d%d",&p,&u1,&v1,&w1);
		
			if (p == 1)                        //必選的邊,加進來,指向同一個父節點
				f[find(v1)] = find(u1),
				ans += w1;
			
			if (p == 2)                             //非必選邊,加進來,不一定處理
				cnt++,
				e[cnt].u = u1,
				e[cnt].v = v1,
				e[cnt].w = w1;	
		}
		
	sort(e+1,e+cnt+1,cmp);                //給點排序
	
	ans += kruskal();                  //跑kruskal
	
	cout<<ans;
	
	return 0; 
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章