Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 19457 | Accepted: 8103 |
Description
Input
Output
Sample Input
3 0 990 692 990 0 179 692 179 0 1 1 2
Sample Output
179 题目:第一行给出一个数n; 然后是n行,每行有n个数,第i行第j列的数代表从i到j的路径长度; 然后再给出一个数q; 下面有q行,每行两个数a,b;代表a,b之间已经有路; 问如果使这n个村子全部连接在一块,最小还要修多少路? kruskal算法: 求加权连通图的最小生成树的算法。kruskal算法总共选择n- 1条边,所使用的贪婪准则是:从剩下的边中选择一条不会产生环路的具有最小耗费的边加入已选择的边的集合中。 注意到所选取的边若产生环路则不可能形成一棵生成树。kruskal算法分e 步,其中e 是网络中边的数目。按耗费递增的顺序来考虑这e 条边,每次考虑一条边。当考虑某条边时, 若将其加入到已选边的集合中会出现环路,则将其抛弃,否则,将它选入。 kruskal算法可以看成并查集的操作 代码:
#include
#include
#include
#include
#define MAX 110
using namespace std;
struct node
{
int a,b;
int dis;
node()
{
a=0;
b=0;
dis=0;
}
};
int visit[MAX];
int f[MAX];
int cmp(const void *a,const void *b)
{
node *p1=(node *)a,*p2=(node *)b;
return p1->dis-p2->dis;
}
void init(int n)
{
memset(f,-1,sizeof(f));
}
int set_find(int x)
{
return f[x]<0?x:f[x]=set_find(f[x]);
}
int main()
{
int n,i,j,a,b,ans,num;
bool flag;
//freopen("\\input.txt","r",stdin);
//freopen("\\output.txt","w",stdout);
scanf("%d",&n);
{
memset(visit,0,sizeof(visit));
init(n);
node map[MAX*MAX];
for(i=1,num=0; i<=n; i++)
{
flag=true;
for(j=1; j<=n; j++)
{
scanf("%d",&b);
if(b==0)
{
flag=false;
continue;
}
if(!flag)
{
map[num].a=i;
map[num].b=j;
map[num++].dis=b;
}
}
}
ans=0;
qsort(map,num,sizeof(map[0]),cmp);//按权值从小到大排序
int q;
scanf("%d",&q);
for(i=1; i<=q; i++)
{
scanf("%d%d",&a,&b);
if(set_find(b)!=set_find(a))//判断是否在同一个树上
f[set_find(b)]=set_find(a);//合并
}
int p1,p2;
for(i=0; i