NYOJ 38 佈線問題(prim和kruskal)兩種方法
阿新 • • 發佈:2018-12-16
佈線問題
時間限制: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);
}
}