树的定义:连通无回路的无向图是一棵树。
有关树的问题:
1、最小生成树。
2、次小生成树。
3、有向图的最小树形图。
4、LCA(树上两点的最近公共祖先)。
5、树的最小支配集、最小点覆盖、最大独立集。
一、最小生成树
解决的问题是:求无向图中边权值之和最小的生成树。
算法有Kruskal和Prim。
Kruskal使用前向星和并查集实现,可以存储重边(平行边),时间复杂度是O(m log m + m),m是边的数量。
Prim使用邻接矩阵建图,不可以存储重边(平行边),如果出现重边,存储的是权值最小的那一条,时间复杂度为O(n*n), n是顶点的数量。使用邻接表建图可能会提高效率。
一般情况下,题目都是比较裸的。难度为易。
模版:建好图以后,直接调用,输出。
prim
1 const int maxn=101,INF=0x3f3f3f3f; 2 int dist[maxn],Map[maxn][maxn],pre[maxn]; 3 //向外延伸的最短边长,记录图信息,记录连接信息 4 bool p[maxn];//1表示点已经在树的,0表示点在树外 5 bool f[maxn][maxn]; 6 int Prim(int n) 7 { 8 int i,j,k,Min,ans=0; 9 for(i=2;i<=n;i++) 10 { 11 p[i]=0; 12 dist[i]=Map[1][i]; 13 pre[i]=1; 14 } 15 dist[1]=0; 16 p[1]=1; 17 for(i=1;i<n;i++) 18 { 19 Min=INF; 20 k=0; 21 for(j=1;j<=n;j++) 22 { 23 if(!p[j]&&dist[j]<Min) 24 { 25 Min=dist[j]; 26 k=j; 27 } 28 } 29 if(k==0) return -1;//G不连通 30 ans+=Min; 31 p[k]=1; 32 for(j=1;j<=n;j++) 33 { 34 if(!p[j]&&Map[k][j]!=INF&&dist[j]>Map[k][j]) 35 { 36 dist[j]=Map[k][j]; 37 pre[j]=k; 38 } 39 } 40 } 41 return ans; 42 }