HDU1863 - 畅通工程:http://acm.hdu.edu.cn/showproblem.php?pid=1863
这题我中午用并查集的方法AC了一次,下午学了Prim。换个姿势,再来一次 = =!
并查集的方法:http://blog.csdn.net/p_rogrammer/article/details/47979073
代码:
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int MAXN = 111;
const int Inf = 1<<31 - 1;
int N,M;
int x,y,z;
vector<int>Mapp[MAXN];
int Cost[MAXN][MAXN],vis[MAXN],Distance[MAXN];
void Initial()
{
for(int i = 0;i < MAXN;i++)
Mapp[i].clear();
fill(vis,vis + MAXN,0);
fill(Distance,Distance + MAXN,Inf);
}
int Prim()
{
int ans = 0, cnt = 0;
Distance[1] = 0;
while(true)
{
int v = -1;//每次都要从第一个村庄开始查找距离 已经连好的村庄 最近的村庄的编号 v
for(int i = 1;i <= M;i++)
if(!vis[i] && (v == -1 || Distance[i] < Distance[v]))
v = i;
// printf("v = %d\n",v);
if(v == -1 || Distance[v] == Inf)return -1;
ans += Distance[v];
// printf("ans = %d\n",ans);
cnt++;//已经连在一起的村庄的数目
if(cnt == M)return ans;
vis[v] = 1;//村庄v标记为访问过
// printf("vis[%d] = %d\n",v,vis[v]);
for(int i = 0;i < Mapp[v].size();i++)
{
int x = Mapp[v][i];//x是与v相连的村庄编号
if(!vis[x] && Cost[v][x] < Distance[x])Distance[x] = Cost[v][x];//更新到已连好的村庄的距离,保证是最短的
}
}
}
int main()
{
while(~scanf("%d",&N) && N)
{
scanf("%d",&M);
Initial();
while(N--)
{
scanf("%d%d%d",&x,&y,&z);
if(x != y)
{
Mapp[x].push_back(y);
Mapp[y].push_back(x);
Cost[x][y] = Cost[y][x] = z;//无向的图,x可到y,y可到x,上同
}
}
int flag = Prim();
if(flag == -1)printf("?\n");
else printf("%d\n",flag);
}
return 0;
}