C. Learning Languages
2013-04-16 19:21
253 查看
C. Learning Languages
今天恰好学了图论中的最小生成树和prim还有克鲁丝卡尔,其中提到了并查集,下面是CF上的一个例子,恰好使用了并查集,这个是别人的代码,当时并不知道这个是什么意思,怎么用,现在看来,任何算法都需要先学习后才能看懂人家的代码,以后才能学会使用。
其中fa[]数组起到的作用就是连接两个集合;
在一个连通图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还有克鲁丝卡尔,其中提到了并查集,下面是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),与圈中边数无关,它适用于边稠密的网络。
相关文章推荐
- 那些年,我还在学习C# 学习笔记续
- Ruby 魔法 学习笔记之一
- sqlserver 数据库学习笔记
- CSS学习笔记Padding 属性中参数的定义与使用
- prototype 1.5 & scriptaculous 1.6.1 学习笔记
- prototype 学习笔记整理
- Oracle学习笔记(六)
- 关于SQLServer2005的学习笔记 XML的处理
- Jquery 基础学习笔记
- ExtJs 学习笔记基础篇 Ext组件的使用第1/2页
- linux Shell学习笔记第五天
- Jquery 学习笔记(二)
- PHP入门学习笔记之一
- 那些年,我还在学习C# 学习笔记
- Ruffy javascript 学习笔记
- JavaScript 学习笔记(十六) js事件
- JavaScript 学习笔记(十二) dom
- JavaScript 学习笔记(十一)
- JavaScript 学习笔记 Black.Caffeine 09.11.28
- javascript高级学习笔记整理