题目大意:
这道题是一个给村庄修路的问题。根据一份调查报告,给出了村庄的个数和任意两个村庄间的距离,还给出了一些村庄间已经存在的道路,要求编程输出:在任意两个村庄都是可达的情况下需要再修路的最短长度。
输入:
一个测试实例,第一行输入一个整数N代表村庄的个数,然后接下来的N行每行输入N个整数,代表编号从N到N的村庄间的距离。然后下一行输入一个整数Q 代表有几条路是已经修好的,接下来的Q行每行输入 两个整数代表这条路的连接的两个村庄的编号。
输出:
最短路径。
解题思路:
求最小生成树的问题。这道题我用的kruscal算法。从输入开始看,第一个整数N,这代表图的节点数,定义一个P数组存储节点,然后用for循环全部初始化,代表每个节点都是互不相关。定义一个结构体数组e存储路径,然后根据输入,要用两层for循环进行输入,在输入的同时给e数组中的元素赋值,赋值之后根据路径长短排序(从小到大),然后输入Q,在Q行中输入路径端点的时候对P数组做处理,先把已经联通了的放到P数组,之后就是算法了,用并查集这种东西去实现,最后输出的就是最短路径。
感想:
这两天这种题做了三道了,在这道题上让我感到有点难办的就是在双重for循环哪里给e数组复制,我本来想的是定义一个二维数组,但是不知道怎么把值赋给一维数组,但是后来发现没有那个必要,循环只是为了输入,然后给e数租赋值,所以就引入了一个K变量,利用每次K++来赋值。
代码如下:
#include<iostream>
#include<algorithm>
using namespace std;
const int N=10;
int father[N];
int road[10][10];
int find(int x)
{
if(x!=father[x])
father[x]=find(father[x]);
return father[x];
}
struct edge
{
int x,y,l;
}e[N*N];
int cmp(edge e1,edge e2)
{
return e1.l<e2.l;
}
int main()
{
int n,m,q,a,b;
cin>>n;
m=n*n;
for(int i=1;i<=n;i++)
father[i]=i;
int k=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
{
cin>>e[k].l;
e[k].x=i;
e[k].y=j;
k++;
}
cin>>q;
for(int i=1;i<=q;i++)
{cin>>a>>b;
father[b]=a;}
sort(e+1,e+1+m,cmp);
int res=0;
for(int i=1;i<=m;i++)
{
int x=find(e[i].x);
int y=find(e[i].y);
if(x!=y)
{res+=e[i].l;
father[x]=y;}
}
cout<<res<<endl;
system("pause");
return 0;
}