图论的复习/(ㄒoㄒ)/

图论基本概念

完全图: 每对顶点之间有边并且只有唯一的一条边.

强连通分量:有向图中任意2点都联通的最大子图.

图的储存

邻接矩阵:也就是一个二维数组,a[i][j]的值代表是否相连.

适用范围:

1.稠密图

2.无多重边

3.数据规模小

链式前向星:(模拟链表)

代码实现(主要部分)

1 void add_eage(int from,int to,int  dis)
2 {
3     eage[++num].next=head[from];
4     eage[num].to=to;
5     eage[num].dis=dis;
6     head[from]=num;
7 }

 

割点&割边:

如果删去,那么原来联通的图就会变成2个或2个以上子图

判断割点:开一个low数组来记录i及i的子孙相连的最高的祖先的访问时间戳

low[u]=min(low[u],low[v]);

判断割边:当且仅当low[v]>dfn[u];

强连通分量Tarjan
 1 void tarjan(int i)//开始搜索...
 2 {
 3     int j;
 4     dfn[i]=low[i]=++times;//记录时间戳
 5     stak[++stp]=i;//压入栈
 6     for(j=head[i];j;j=a[j].next)
 7     {
 8         int k=a[j].to;
 9         if(!dfn[j])
10         {
11             tarjan(j);
12             if(low[j]<low[i]) low[i]=low[j];
13         }
14         else if(instak[j]&&dfn[j]<low[i]) low[i]=dfn[j];
15     }
16     if(dfn[i]==low[i])//判断改点是否为根节点
17     {
18         cnt++;//定义在最外面
19         do
20         {
21             j=stak[stop--];
22             instak[j]=false;
23             belong[j]=cnt;
24         }while(i!=j);
25     }
26 }
27 //cnt代表多少个强连通分量

 

最短路

1.Dijkstra:不含负权

思路:每次找到离源点最近的一个点进行扩展,最终得到源点到其余所有点的最短路径,不含负权

2.Bellman-ford:有负权,不含负权回路

这个就转变成对边的松弛

for(int i=2; i<=n; i++)
24     {
25          int mindist = MAXINT;
26          int u = v0;                               // 找出当前未使用的点j的dist[j]最小值
27          for(int j=1; j<=n; ++j)
28             if((!S[j]) && dist[j]<mindist)
29             {
30                   u = j;                             // u保存当前邻接点中距离最小的点的号码 
31                   mindist = dist[j];
32             }
33          S[u] = true; 
34          for(int j=1; j<=n; j++)
35              if((!S[j]) && A[u][j]<MAXINT)
36              {
37                  if(dist[u] + A[u][j] < dist[j])     //在通过新加入的u点路径找到离v0点更短的路径  
38                  {
39                      dist[j] = dist[u] + A[u][j];    //更新dist 
40                      prev[j] = u;                    //记录前驱顶点 
41                   }
42               }
43      }

 

3.SPFA:kuai

 1  while (!Q.empty())
 2     {
 3         int u = Q.front();
 4         Q.pop();
 5         visited[u] = 0;
 6         for (int v = 0; v < vertex_num; v++)
 7         {
 8             if (matrix[u][v] != INT_MAX)  //u与v直接邻接
 9             {
10                 if (dist[u] + matrix[u][v] < dist[v])
11                 {
12                     dist[v] = dist[u] + matrix[u][v];
13                     path[v] = u;
14                     if (!visited[v])
15                     {
16                         Q.push(v);
17                         enqueue_num[v]++;
18                         if (enqueue_num[v] >= vertex_num)
19                             return false;
20                         visited[v] = 1;
21                     }
22                 }
23             }
24         }
25     }

最小生成树太简单

 

posted @ 2019-02-13 15:04  K&S&T  阅读(125)  评论(0编辑  收藏  举报