61.新的开始(最小生成树)
文件名:newstart.cpp
輸入輸出文件:newstart.in、newstart.out
時空:50M,1s
【題目描述】
發(fā)展采礦業(yè)當(dāng)然首先得有礦井, 小 FF 花了上次探險獲得的千分之一的財富請人在島
上挖了 n 口礦井, 但他似乎忘記考慮的礦井供電問題……
為了保證電力的供應(yīng), 小 FF 想到了兩種辦法:
1、 在這一口礦井上建立一個發(fā)電站, 費用為 v(發(fā)電站的輸出功率可以供給任
意多個礦井)。
2、 將這口礦井與另外的已經(jīng)有電力供應(yīng)的礦井之間建立電網(wǎng), 費用為 p。
小 FF 希望身為”NewBe_One" 計劃首席工程師的你幫他想出一個保證所有礦井電力供
應(yīng)的最小花費。
【輸入格式】
第一行一個整數(shù) n, 表示礦井總數(shù)。
第 2~n+1 行,每行一個整數(shù), 第 i 個數(shù) v[i]表示在第 i 口礦井上建立發(fā)電站的費用。
接下來為一個 n*n 的矩陣 P, 其中 p[ i , j ]表示在第 i 口礦井和第 j 口礦井之間建立
電網(wǎng)的費用(數(shù)據(jù)保證有 p[ i, j ] = p[ j, i ], 且 p[ i, i ]=0) 。
【輸出格式】
僅一個整數(shù), 表示讓所有礦井獲得充足電能的最小花費。
【輸入樣例】
4
5
4
NOIP2010 模擬試題
4
3
0 2 2 2
2 0 3 3
2 3 0 4
2 3 4 0
【輸出樣例】
9
輸出樣例說明:
小 FF 可以選擇在4號礦井建立發(fā)電站然后把所有礦井都與其建立電網(wǎng),總花費是
3+2+2+2 = 9。
【數(shù)據(jù)范圍】
對于30%的數(shù)據(jù):1<=n<=50;
對于100%的數(shù)據(jù):1<=n<=300; 0<=v[i], p[i,j] <=10^5.
思路:因為不一定僅僅建立一個發(fā)電站,那么就建立一個超級源點,把所有點建立發(fā)電站的費用設(shè)為到這一點的路徑,然后在這張圖中跑一邊kruskal算法就行了?
代碼:
#include
using namespace std;
#include
#include
int n;long long sum=0;
int minfdz=999999,t;//t tiao bian
struct Edge{
?int u,v,w;
};
Edge edge[302*302];
int fdz[301],father[301];
int find(int);
void unionn(int,int);
int cmp(const Edge &a,const Edge &b)
{
?return a.w
}
void kruskal();
void input();
int main()
{
?freopen("newstart.in","r",stdin);
?freopen("newstart.out","w",stdout);
?input();
?kruskal();
?cout<<sum<<endl;
?fclose(stdin);
?fclose(stdout);
?return 0;
}
void kruskal()
{
?int k=0;
?for(int i=1;i<=n+1;++i)
?father[i]=i;
?sort(edge+1,edge+t+1,cmp);
?for(int i=1;i<=t;++i)
?{
??int r1=find(edge[i].u);
??int r2=find(edge[i].v);
??if(r1!=r2)
??{
???unionn(r1,r2);
???sum+=edge[i].w;
???k++;
???if(k==n) return;
??}
?}
?
}
void input()
{
?scanf("%d",&n);
?t=0;
?for(int i=1;i<=n;++i)
?{
??scanf("%d",&fdz[i]);
??if(fdz[i]
??minfdz=fdz[i];
??edge[++t].u=n+1;
??edge[t].v=i;
??edge[t].w=fdz[i];
??edge[++t].v=n+1;
??edge[t].u=i;
??edge[t].w=fdz[i];
?}
?for(int i=1;i<=n;++i)
?? for(int j=1;j<=n;++j)
?? {
?? ?edge[++t].u=i;
?? ?edge[t].v=j;
?? ?scanf("%d",&edge[t].w);
?? }
}
int find(int x)
{
?if(father[x]!=x) father[x]=find(father[x]);
?return father[x];
}
void unionn(int a,int b)
{
?father[b]=a;
}
?
轉(zhuǎn)載于:https://www.cnblogs.com/c1299401227/p/5370753.html
總結(jié)
以上是生活随笔為你收集整理的61.新的开始(最小生成树)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: docker 学习手冊-中文版下载
- 下一篇: (ssh整合web导出excel)在ss