您的位置:首页 > 其它

C. Learning Languages

2013-04-16 19:21 253 查看
C. Learning Languages

今天恰好学了图论中的最小生成树和prim还有克鲁丝卡尔,其中提到了并查集,下面是CF上的一个例子,恰好使用了并查集,这个是别人的代码,当时并不知道这个是什么意思,怎么用,现在看来,任何算法都需要先学习后才能看懂人家的代码,以后才能学会使用。


其中fa[]数组起到的作用就是连接两个集合;



// File Name: 170c.cpp
// Author: rudolf
// Created Time: 2013年03月04日 星期一 16:19:34

#include<vector>
#include<list>
#include<map>
#include<set>
#include<deque>
#include<stack>
#include<bitset>
#include<algorithm>
#include<functional>
#include<numeric>
#include<utility>
#include<sstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<ctime>

using namespace std;
int fa[200];
bool visit[200];
void init()
{
for(int k=0;k<200;k++)
fa[k]=k;
}

int find(int x)
{
return x==fa[x]?x:fa[x]=find(fa[x]);
}

bool Union(int a,int b)
{
a=find(a);
b=find(b);
if(a==b)
return false;
fa[a]=b;
return true;
}

int a[200];
int main()
{
int n,m;
int ans;
while(cin>>n>>m)
{
memset(visit,false,sizeof(visit));
init();
ans=0;
int flag=0;
for(int i=0,num;i<n;i++)
{
cin>>num;
if(num==0)
ans++;
for(int j=0;j<num;j++)
{
flag=1;
cin>>a[j];
visit[a[j]]=true;
for(int z=0;z<j;z++)
Union(a[j],a[z]);
}
}
for(int i=1;i<=m;i++)
if(visit[i]&&fa[i]==i)
ans++;
cout<<ans-flag<<endl;
}
return 0;
}
最小生成树

在一个连通图G中,如果它的全部定点和一部分边构成一个子图G’,并且边集中的边既将所有的顶点连通又不形成回路,则称子图G’是原图的一棵生成树。


对于一个连通网(即连通带权图)来说,生成树不同,每棵树的权(即树中所有边上的权值和)也可能不同,权最小的生成树称为最小生成树。




最小生成树的性质(MST性质):

设G=(V,E)是一个连通网络,U是顶点集V的一个真子集。若(U,V)是G中一条(一个端点在U中,另一个断点不在U中的边),且(U,V)具有最小权值,则一定存在G的一棵最小生成树包括此边(U,V)。

a.必须使用该网络中的边来构造最小生成树;

b.必须使用且仅使用n-1条边来连接网络中的n个顶点;

c.不能使用产生回路的边;

从连通网络N={V,E}中的某个顶点U0出发,选择与它相关联的具有最小权值的边(U0, V),将其顶点加入到生成树的顶点集合U中。以后每一步从一个顶点在U中,而另一个顶点不再U中的各条边中,选取权值最小的边(U,V),把它的顶点加入到集合U中,如此继续下去,直到网络中的所有顶点都加入到生成树顶点集U中为止



利用prim算法建立最小生成树Void Graph<string, float>…
Prim(MinSpanTree&T){
int NumVertuces=VertucesList.Last;    //图顶点数
Float *lowcost=new float[NumVertices];
Int * nearvex=new int[NumVertices];
For(int i=0;i<NumVertices;i++){//顶点0到各边的代价及最短带权路径
Lowcost[i]=Edge[0][i];
Nearvex[i]=0;}
Nearvex[0]=-1;//顶点0加到生成树顶点集合
MSTEdgeNode  e;
For(i=1;i<NumVertices;i++){循环n-1次,加入n-1条边
Float min=MAXNUM;int v=0;
For(int j=0;j<NumVertices;j++)
If(nearvex[j]!=-1&&lowcost[j]<min){//求生成树外顶点到生成树内顶点具有最小权值的边,v是当前具有最小权值的边的位置
V=j;min=lowcost[j];}If(V){      //v==0表示再也找不到要求的顶点了
E.tail=nearvex[v];	e.head=v;
E.cost=lowcost[v];
T.insert(e);		//选出的边加入生成树
Nearvex[v]=-1;	//作该边已加入生成树的标记
For(j=1;j<NumVertices;j++)
If(nearvex[j]!=-1&&Edge[v][j]<lowcost[j]){//需要修改
Lowcost[j]=Edge[v][j];
Nearvex[j]=v;}}}}

时间复杂度分析
设连通网络有n个顶点,则该算法的时间复杂度为O(n2),与圈中边数无关,它适用于边稠密的网络。



内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  学习笔记 hut