试题编号: 201412-4
试题名称: 最优灌溉
时间限制: 1.0s
内存限制: 256.0MB
问题描述:
问题描述
雷雷承包了很多片麦田,为了灌溉这些麦田,雷雷在第一个麦田挖了一口很深的水井,所有的麦田都从这口井来引水灌溉。
为了灌溉,雷雷需要建立一些水渠,以连接水井和麦田,雷雷也可以利用部分麦田作为“中转站”,利用水渠连接不同的麦田,这样只要一片麦田能被灌溉,则与其连接的麦田也能被灌溉。
现在雷雷知道哪些麦田之间可以建设水渠和建设每个水渠所需要的费用(注意不是所有麦田之间都可以建立水渠)。请问灌溉所有麦田最少需要多少费用来修建水渠。
输入格式
输入的第一行包含两个正整数n, m,分别表示麦田的片数和雷雷可以建立的水渠的数量。麦田使用1, 2, 3, ……依次标号。
接下来m行,每行包含三个整数ai, bi, ci,表示第ai片麦田与第bi片麦田之间可以建立一条水渠,所需要的费用为ci。
输出格式
输出一行,包含一个整数,表示灌溉所有麦田所需要的最小费用。
样例输入
4 4
1 2 1
2 3 4
2 4 2
3 4 3
样例输出
6
样例说明
建立以下三条水渠:麦田1与麦田2、麦田2与麦田4、麦田4与麦田3。
评测用例规模与约定
前20%的评测用例满足:n≤5。
前40%的评测用例满足:n≤20。
前60%的评测用例满足:n≤100。
所有评测用例都满足:1≤n≤1000,1≤m≤100,000,1≤ci≤10,000
#include<iostream>
#include<stdlib.h>
#include<vector>
using namespace std;
struct Closeset//辅助数组结构体
{
int vexcode;
int lowcost;
};
struct MGraph
{
vector<vector<int> > arcs;//邻接矩阵
int vexnum, arcnum;//图包含的顶点数和边数
};
bool CreateGraph(MGraph& G)//无向图的创建
{
int i, j;
cin >> G.vexnum >> G.arcnum;
G.arcs.resize(G.vexnum+1);
for (i = 0; i <= G.vexnum; i++) // 邻接矩阵初始化
{
G.arcs[i].resize(G.vexnum + 1);
for (j = 0; j <= G.vexnum; j++)
{
G.arcs[i][j] = 10001;
}
}
for (int k = 0; k < G.arcnum; k++)//为边赋权值
{
int Ci;
cin >> i >> j>>Ci;
G.arcs[i][j] =Ci;
G.arcs[j][i] =Ci;
}
return true;
}
int MinSpanningTree_Prim(MGraph &G, int v)//普里姆算法最小生成树
{
int sum = 0;//记录最小生成树的权值总和
int i, j, k = 0;
Closeset* closest=(Closeset*)malloc(sizeof(closest)*(G.vexnum+1));
if (!closest)
exit(1);
for (j = 1; j <= G.vexnum; j++)//对closest进行初始化处理
{
closest[j].lowcost = G.arcs[v][j];//从顶点v出发
closest[j].vexcode = v;
}
closest[v].lowcost = 0;//v到v的最短长度为0(表示v已经被选中)
for (i = 2; i <= G.vexnum; i++)//将剩余顶点加入最小生成树
{
int min =10000;
//Step1:在数组closest中寻找lowcost的最小非零值
for (j = 1; j <=G.vexnum; j++)
{
if (closest[j].lowcost != 0 && closest[j].lowcost < min)
{
min = closest[j].lowcost;
k = j;//记录最小值索引
}
}
//Step2:选定本轮的最小权值边
sum += closest[k].lowcost;
//debug cout << "建立水渠:" << closest[k].vexcode << " " << k << endl;
closest[k].lowcost = 0;
//Step3:更新closest数组的信息
for (j = 1; j <=G.vexnum; j++)
{
if (G.arcs[k][j] < closest[j].lowcost)//不在树上的顶点到新加入树的顶点k的距离比原来的小
{
closest[j].lowcost = G.arcs[k][j];
closest[j].vexcode = k;
}
}
}
//所有顶点均已加入
free(closest);
return sum;
}
int main()
{
MGraph M;
CreateGraph(M);//初始化图
cout << MinSpanningTree_Prim(M,1);
return 0;
}
只有50分求解答
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=1005;
const int inf=0x3fffffff;
int g[maxn][maxn],n,d[maxn];
bool vis[maxn]={false};
struct node{//入队的结点
int to,cost;
friend bool operator < (node a,node b){
return a.cost>b.cost;
}
};
int prim(){//prim算法求最小生成树
int ans=0;
fill(d,d+maxn,inf);
priority_queue<node> q;
q.push((node){1,0});
while(!q.empty()){
node now=q.top();
q.pop();
int x=now.to;
if(vis[x]) continue;
ans+=now.cost;
vis[x]=true;
for(int i=1;i<=n;i++){
if(g[x][i]!=inf&&!vis[i]&&d[i]>g[x][i]){
d[i]=g[x][i];
q.push((node){i,g[x][i]});
}
}
}
return ans;
}
int main(){
int m,a,b,c;
fill(g[0],g[maxn-1]+maxn,inf);
scanf("%d%d",&n,&m);
while(m--){
scanf("%d%d%d",&a,&b,&c);
g[a][b]=g[b][a]=c;
}
printf("%d\n",prim());
return 0;
}