1. 程式人生 > >NYOJ 38 佈線問題(prim和kruskal)兩種方法

NYOJ 38 佈線問題(prim和kruskal)兩種方法

佈線問題

時間限制:1000 ms  |  記憶體限制:65535 KB

難度:4

輸入

第一行是一個整數n表示有n組測試資料。(n<5)
每組測試資料的第一行是兩個整數v,e.
v表示學校裡樓的總個數(v<=500)
隨後的e行裡,每行有三個整數a,b,c表示a與b之間如果建鋪設線路花費為c(c<=100)。(哪兩棟樓間如果沒有指明花費,則表示這兩棟樓直接連通需要費用太大或者不可能連通)
隨後的1行裡,有v個整數,其中第i個數表示從第i號樓接線到外界供電設施所需要的費用。( 0<e<v*(v-1)/2 )
(樓的編號從1開始),由於安全問題,只能選擇一個樓連線到外界供電裝置。
資料保證至少存在一種方案滿足要求。

輸出

每組測試資料輸出一個正整數,表示鋪設滿足校長要求的線路的最小花費。

樣例輸入

1
4 6
1 2 10
2 3 10
3 1 10
1 4 1
2 4 1
3 4 1
1 3 5 6

樣例輸出

4

描述

南陽理工學院要進行用電線路改造,現在校長要求設計師設計出一種佈線方式,該佈線方式需要滿足以下條件:
1、把所有的樓都供上電。
2、所用電線花費最少

此類是屬於簡單的最小生成樹題,兩種演算法的去bilibili看懂原理基本就可以自己打程式碼了(不過的看了kruskal演算法原理還是有點懵逼,不太會怎麼打,一直在wa,runtim error,(QAQ)(太菜了~)

prim演算法程式碼

#include<cstdio>
#include<iostream>
#include<cstring> 
#include<algorithm>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<queue>
#include<vector>
#include<assert.h>
#include<map>
#include<set>
#include<stack>
#define in(a) scanf("%d",&a)
#define ind(a) scanf("%lld",&a)
#define inc(a) scanf("%c",&a)
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII; 
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); 
for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn=550;
const int inf=0x3f3f3f3f;
int ma[maxn][maxn];
int low[maxn];
bool vis[maxn];
int v;
int prim()
{
	vis[1]=1;
	for(int i=1;i<=v;i++) low[i]=ma[1][i];
	int pos;
	int ans=0;
	for(int i=0;i<v-1;i++)
	{
		int minx=inf;
		for(int j=1;j<=v;j++)
		{
			if(!vis[j]&&low[j]<minx) 
			{
				minx=low[j];
				pos=j;
			}
		}
		ans+=low[pos];
		vis[pos]=1;
		
		for(int j=1;j<=v;j++)
		{
			if(!vis[j]&&low[j]>ma[pos][j]) low[j]=ma[pos][j];
		}
	}
	return ans;
}
int main()
{
	int t;
	in(t);
	while(t--)
	{
		int e;
		in(v);in(e);
		memset(ma,inf,sizeof(ma));
		rep(i,0,e)
		{
			int a,b,c;
			scanf("%d%d%d",&a,&b,&c);
			ma[a][b]=ma[b][a]=c;
		}
		mem(vis);
		mem(low);
		int minx=inf;
		int x;
		rep(i,0,v)
		{
			in(x);
			if(x<minx) minx=x;
		}
		printf("%d\n",prim()+minx);
	}
	
 } 

kruskal演算法程式碼:

 
#include<cstdio>
#include<iostream>
#include<cstring> 
#include<algorithm>
#include<string>
#include<cmath>
#include<stdlib.h>
#include<queue>
#include<vector>
#include<assert.h>
#include<map>
#include<set>
#include<stack>
#define in(a) scanf("%d",&a)
#define ind(a) scanf("%lld",&a)
#define inc(a) scanf("%c",&a)
#define mem(a) memset(a,0,sizeof(a))
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define per(i,a,n) for (int i=n-1;i>=a;i--)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define SZ(x) ((int)(x).size())
typedef vector<int> VI;
typedef long long ll;
typedef pair<int,int> PII; 
const ll mod=1000000007;
ll powmod(ll a,ll b) {ll res=1;a%=mod; assert(b>=0); 
for(;b;b>>=1){if(b&1)res=res*a%mod;a=a*a%mod;}return res;}
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int maxn=550;
const int inf=0x3f3f3f3f;
struct node
{
	int x,y;
	int cost;
};
//node a[maxn];
int fa[maxn];
int kruskal(node *a,int v)
{
	int i,j,s;
	i=j=s=0;;
	while(j<v-1)
	{
		int x=fa[a[i].x-1];
		int y=fa[a[i].y-1];
		if(x!=y)
		{
			for(int k=0;k<v;k++)
				if(fa[k]==y)
					fa[k]=x;
			s+=a[i].cost;
			j++;
		}
		i++;
	}
	return s;
}
bool cmp(const node &a,const node &b)
{
	return a.cost<b.cost;
}
int main()
{
	int t;
	in(t);
	int v,e;
	while(t--)
	{
		in(v);in(e);
		node a[e];
		rep(i,0,e)
		{
			in(a[i].x);
			in(a[i].y);
			in(a[i].cost);
		}
		sort(a,a+e,cmp);
		
		int minx=inf;
		int x;
		rep(i,0,v)
		{
			in(x);
			if(x<minx) minx=x;
			fa[i]=i;
		}
		printf("%d\n",kruskal(a,v)+minx);
	}
}