版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wingrez/article/details/89684094
畅通工程
来源:HDU
标签:最小生成树,合并查找算法
参考资料:
相似题目:
题目
省政府“畅通工程”的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可)。经过调查评估,得到的统计表中列出了有可能建设公路的若干条道路的成本。现请你编写程序,计算出全省畅通需要的最低成本。
输入
测试输入包含若干测试用例。每个测试用例的第1行给出评估的道路条数 N、村庄数目M ( < 100 );随后的 N 行对应村庄间道路的成本,每行给出一对正整数,分别是两个村庄的编号,以及此两村庄间道路的成本(也是正整数)。为简单起见,村庄从1到M编号。当N为0时,全部输入结束,相应的结果不要输出。
输出
对每个测试用例,在1行里输出全省畅通需要的最低成本。若统计数据不足以保证畅通,则输出“?”。
输入样例
3 3
1 2 1
1 3 2
2 3 4
1 3
2 3 2
0 100
输出样例
3
?
参考代码
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int MAXN=105;
struct UnionFind{
int ufset[MAXN];
int size; //连通分量个数
int init(int N){ //N为节点数
size=N;
for(int i=1;i<=N;i++){ //节点标号从1开始
ufset[i]=i;
}
}
int find(int v){
while(v!=ufset[v]) v=ufset[v];
return v;
}
void join(int v,int u){
int ra=find(v);
int rb=find(u);
if(ra==rb) return;
ufset[ra]=rb;
size--;
}
};
struct Edge{
int u; //边的一个顶点
int v; //边的另一个顶点
int w; //边的权值
Edge(int u,int v,int w):u(u),v(v),w(w){}
bool operator < (const Edge &e) const {
return w>e.w;
}
};
struct Prim{ //Prim算法,计算最小生成树,适用有向或无向图
vector<Edge> adj[MAXN]; //agj[v]:与v相连的边
priority_queue<Edge> pq; //优先队列,存放横切边
vector<Edge> mst; //最小生成树
bool vis[MAXN]; //访问标志
void prim(int s){ //从起点s开始
visit(s);
while(!pq.empty()){
Edge e=pq.top();
pq.pop();
if(vis[e.u] && vis[e.v]) continue;
mst.push_back(e);
if(!vis[e.u]) visit(e.u);
if(!vis[e.v]) visit(e.v);
}
}
void init(){ //初始化
for(int i=0;i<MAXN;i++) adj[i].clear();
while(!pq.empty()) pq.pop();
mst.clear();
memset(vis,0,sizeof(vis));
}
void addEdge(int u,int v,int w){
adj[u].push_back(Edge(u,v,w));
}
void visit(int u){ //设置访问标志,并将与v相邻结点(未被访问)的边加入优先队列中
vis[u]=true;
for(vector<Edge>::iterator i=adj[u].begin(); i!=adj[u].end();i++)
if(!vis[(*i).v]) pq.push(*i);
}
};
UnionFind uf;
Prim prim;
int N,M;
int u,v,w;
int main(){
while(scanf("%d%d",&N,&M)==2 && N){
uf.init(M);
prim.init();
for(int i=0;i<N;i++){
scanf("%d%d%d",&u,&v,&w);
prim.addEdge(u,v,w);
prim.addEdge(v,u,w);
uf.join(u,v);
}
if(uf.size!=1) printf("?\n");
else {
int ans=0;
prim.prim(1);
for(int i=0;i<prim.mst.size();i++){
ans+=prim.mst[i].w;
}
printf("%d\n",ans);
}
}
return 0;
}