【总结】图论算法

1:最小生成树算法(Kruscal算法)

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
struct struct_edges
{   int bv,tv; //bv 起点  tv 终点
     double w; //权值};
struct_edges edges[10100]; //边集
struct struct_a
{   double x;double y;};
struct_a arr_xy[101];
int point[101],n,e;  //n 顶点数, e 边数(注意是无向网络)
double sum;
int kruscal_f1(int point[], int v)
{  int i = v;
     while(point[i] > 0)     i = point[i]; return i;}
bool UDlesser(struct_edges a, struct_edges b)
{return a.w < b.w;}
void kruscal() //只需要准备好n,e,递增的边集edges[]即可使用
{  int v1,v2,i,j;
     for(i=0; i<n ;i++)     point[i]=0;
     i = j = 0;
     while(j<n-1 && i<e) {
          v1 = kruscal_f1(point, edges[i].bv);
          v2 = kruscal_f1(point, edges[i].tv);
          if(v1 != v2) {
               sum += edges[i].w; //注意sum初始为0
               point[v1]=v2;
               j++;}
          i++;}}
int main()
{  int k,i,j;cin>>n; k=0;
     while(n != 0) {
          sum=0; k++;
          for(i=0; i<n ;i++)
               cin>>arr_xy[i].x>>arr_xy[i].y; e=0;
          for(i=0; i<n ;i++) //从0开始计数
               for(j=i+1; j<n ;j++) //注意是无向网络
               {   if(i == j) continue;
                    edges[e].bv=i; edges[e].tv=j;
                    edges[e].w=sqrt((arr_xy[i].x-arr_xy[j].x)*(arr_xy[i].x-arr_xy[j].x)+(arr_xy[i].y-arr_xy[j].y)*(arr_xy[i].y-arr_xy[j].y));
                    e++;}
         sort(edges,edges+e,UDlesser);  //得到一个递增的边集,注意是从0开始计数
               kruscal();
               printf("Case #%d:\n",k);  //cout<<"Case #"<<k<<":"<<endl;
               printf("The minimal distance is: %.2f\n",sum);  //输出sum
               cin>>n;
               if(n != 0) printf("\n");}}

2:最小生成树算法  (Prim算法)

#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;
double sum, arr_list[101][101], min;
int i, j, k=0, n;
struct struct_a
{   float x;  float y;};
struct_a arr_xy[101];
struct struct_b
{int point;float lowcost;};
struct_b closedge[101];
void prim(int n) //prim 需要准备:n顶点数arr_list[][]顶点的邻接矩阵也是从0开始计数
{int i,j,k;k=0;
     for(j=0; j<n ;j++) {
          if(j != k) {
               closedge[j].point = k; closedge[j].lowcost = arr_list[k][j];}}
     closedge[k].lowcost=0;
     for(i=0; i<n ;i++) {
          min=10000;
          for(j=0; j<n ;j++) {
               if (closedge[j].lowcost != 0 && closedge[j].lowcost < min) {
                    k = j;
                    min = closedge[j].lowcost;}}
          sum += closedge[k].lowcost;  //不要改成sum+=min;  sum即为所求值
          closedge[k].lowcost = 0;
          for(j=0; j<n ;j++) {
               if(arr_list[k][j] < closedge[j].lowcost) {
                    closedge[j].point = k;
                    closedge[j].lowcost = arr_list[k][j];} } }}
/* arr_list[][]= Wij 如果Vi, Vj有边    0   如果i=j   无限大 如果没有边*/
int main()
{   cin>>n;
     while(n != 0) {
          sum=0; k++;
          for(i=0; i<n ;i++)
               cin>>arr_xy[i].x>>arr_xy[i].y;
          for(i=0; i<n ;i++)
               for(j=0; j<n ;j++) //得到邻接矩阵arr_list[][]
                    arr_list[i][j]=arr_list[j][i]=sqrt((arr_xy[i].x-arr_xy[j].x)*(arr_xy[i].x-arr_xy[j].x)+(arr_xy[i].y-arr_xy[j].y)*(arr_xy[i].y-arr_xy[j].y));
          prim(n); cout<<"Case #"<<k<<":"<<endl;
          printf("The minimal distance is: %.2f\n",sum);
          cin>>n;
          if(n!=0)     printf("\n"); }}

3:单源最短路径(Bellman-ford算法)

struct node {
    int e,v;
    node(int a = 0,int b = 0)
        : e(a), v(b) {}};
vector< vector<node> > path;
int n,p,q;
int dist[1000100];
/*
*    SPFA (Shortest Path Faster Algorithm)
*    Bellman-Ford算法的一种队列实现,减少了不必要的冗余计算
*    返回值为false,说明队列不为空,存在负权环
*/
bool SPFA()
{  int i,j,k,now,l;node next;bitset <1000100> vis;
queue< int > SQ;memset(dist,-1,sizeof(dist));
    SQ.push(1);vis[1] = true;dist[1] = 0;
    for (i=0;i<=n;i++) {
        l = SQ.size();
        if (l == 0) break;
        while (l--) {
            now = SQ.front();SQ.pop();vis[now] = false;
            for (j=path[now].size()-1;j>=0;j--) {
                next = path[now][j];
                if (dist[next.e]==-1 || dist[next.e] > dist[now]+next.v) {
                    dist[next.e] = dist[now]+next.v;
                    if(!vis[next.e]) {
                        SQ.push(next.e);vis[next.e] = true;}}}}}
    return SQ.empty();}

4单源最短路径(Dijkstra算法)

int matrix[200][200],n;          //matrix[][], 30000表示无限大,即无边.否则为有边,其值为边的权值
void Dijkstra(int x,int y)     //起点Vx 终点Vy
{int i,j,k,path[40000],mark[40000];
     int min,dist[40000];
     for(i=1;i<=n;i++) { mark[i] = 0;dist[i] = matrix[x][i]; path[i] = x;}
     mark[x] = 1;
     do { min=30000; k=0;
          for(i=1;i<=n;i++)
               if(mark[i]==0 && dist[i]<min) {
                    min = dist[i];
                    k = i;}
          if(k) {
               mark[k] = 1;
               for(i=1;i<=n;i++)
                    if(matrix[k][i]<30000 && min+matrix[k][i]<dist[i]) {
                         dist[i] = min + matrix[k][i];
                         path[i] = k; }}
     }while(k);
     cout<<dist[y]<<endl;     //dist[y] 的值就是从Vx 到 Vy 的最短路径值
     //如果希望得到路径,加入如下代码:
     do {cout<<k<<"<--";k = path[k];
     }while(k!=x);
     cout<<x<<endl;}

5:全源最短路径(Folyd算法)

void Floyd()
{  int i,j,k;
    for(k=0;k<vertex_number;k++) {
        for(i=0;i<vertex_number;i++) {
            for(j=0;j<vertex_number;j++) {
                if((graph[i][k]==-1) || (graph[k][j]==-1))     continue;
                if((graph[i][j]==-1) || (graph[i][j] > graph[i][k]+graph[k][j]))
                {
                    graph[i][j] = graph[i][k]+graph[k][j];   /*最短路径值*/
                    path[i][j] = k;     /*最短路径*/ }
                    }
           }
       }
}
                        

6:拓扑排序

/**** **** **** **** **** ****
*    Function Name :        拓扑排序
**** **** **** **** **** ****/
//degree[]    每个结点的入度
//f[]            每个结点所在的层
void Toplogical_sort()
{   int i,j;bool p=true;top=0;
     while(p) { p=false; top++;
          for(i=1;i<=n;i++)
            if(degree[i]==0) {p=true; f[i]=top; }
          for(i=1;i<=n;i++)
               if(f[i]==top) {
                    for(j=1;j<=n;j++)
                         if(map[i][j])     degree[j]--; degree[i]=-1;    }        }
    top--;    } 
时间: 2024-08-06 07:59:00

【总结】图论算法的相关文章

图论算法之最短路径

图论算法之最短路径 作者:jasonkent27 转载请注明出处:www.cnblogs.com/jasonkent27 1. 前言 1.1 最短路引入 小明和小天现在住在海口(C1),他们俩计划暑假到三亚(C4)玩一趟,在海口和三亚之间有许多中间城市(文昌,临高,乐东,万宁...)图中的边上的数字是他们到达该城市必须的花费,现在需要你帮他们俩找出一条从海口到三亚的最省钱的路径出来. 等等,图中的边的weight怎么会有负的呢?你暂且可以这么理解吧.图中的边上的weight可以当作他们旅途中必须

图论算法----强连通

poj 2186 Popular Cows 分析:直接求一下强连通分量,对于同一个强连通分量里面的结点状态是相同的,要求有多少个人被其他所有的人都认可,只有可能是拓扑排序的最后一个强连通的结点个数,判断一下其他节点是否都可以到该联通分量就ok了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <set> 5 #include <algorithm>

基础图论算法导引

ACM中常用图论算法 1. 拓扑排序 -> 拓扑排序的原理及其实现 2. 最短路径算法 -> 最短路算法总结 差分约束系统 -> 差分约束 前k短路 -> 前K短路径问题 3. 最小生成树问题扩展 -> 最?小?生?成?树?问?题?的?拓?展  最优比率生成树 -> 最优比率生成树 最小k度限制生成树 -> IOI2004国家集训队论文,由汪汀所著(网盘内有) 或者刘汝佳的黑书内有 裸题 poj1639 题解 4. 二分图匹配 -> 二分图的最大匹配.完美匹

图论算法(5) --- 双向广搜求最短路(Bidirectional Breadth First Search)

我们知道,在图论算法中,求最短路是最基本的问题.在求最短路的问题中,应用双向广度优先搜索算法,又是一个较为高效而又简单的算法.所谓双向广度优先搜索,其实根本的核心还是BFS,只不过它是从起点和终点两头同时搜索,大大提高了搜索效率,又节省了搜索空间.广搜大家知道当然是用队列来实现了,在这里,要注意的问题就是,我们必须按层搜索,正向队列处理一层,接着去处理反向队列的一层,按层交替进行,而不是按节点交替进行,这点需要注意,其他的也就很简单了,代码中附有注释,如有问题请留言. package simil

图论算法-Tarjan模板 【缩点;割顶;双连通分量】

图论算法-Tarjan模板 [缩点:割顶:双连通分量] 为小伙伴们总结的Tarjan三大算法 Tarjan缩点(求强连通分量) int n; int low[100010],dfn[100010]; bool ins[100010]; int col[100010];//记录每个点所属强连通分量(即染色) vector<int> map[100010]; stack<int> st; int tot;//时间戳 int colnum;//记录强连通分量个数 void tarjan(

再谈排序与图论算法

排序 1.主存能放下的数据进行排序称为内部排序,反之称为外部排序(磁盘上).2.任何进行交换相邻元素进行排序的算法均需要O(N2)的复杂度,任何进行比较的排序算法至少需要O(N*log(N))的算法复杂度. 3.堆排序和归并排序的时间复杂度平均和最坏均为O(N*log(N)) 4.Java中执行一次对象比较是比较昂贵的,移动则是相对节省的,因此归并排序是java的默认泛型排序算法.C++中默认的是快速排序,比较耗费小:快排对于基本类型均具有最快速度.快速排序选取枢纽元的时候采用三数取中,切勿采用

【WIP_S9】图论算法

创建: 2018/06/01 图的概念 有向边 有向图 无向边 无向图 点的次数: 点连接的边的数量 闭路: 起点和重点一样 连接图: 任意两点之间都可到达 无闭路有向图: 没有闭路的有向图 森林: 互素的树的集合 生成树: 含有图里所有点的树 生成树林: 所有生成树的并集         图论算法的应用     ● 电路的元件关系 ● 交通网 ● 电脑网络(本地网络, 互联网, web等) ● 数据库(实体关系图(ER图))                                  

[算法模版]Tarjan爷爷的两种图论算法

[算法模版]Tarjan爷爷的两种图论算法 前言 Tarjan爷爷发明了很多图论算法,这些图论算法有很多相似之处(其中一个就是我都不会).这里会对这三种算法进行简单介绍. 定义 强连通(strongly connected): 在一个有向图\(G\)里,设两个点$ a, b \(发现,由\)a\(有一条路可以走到\)b\(,由\)b\(又有一条路可以走到\)a\(,我们就叫这两个顶点\)(a,b)$强连通. 强连通图: 如果 在一个有向图\(G\)中,每两个点都强连通,我们就叫这个图,强连通图.

图论算法的数学模型

目录 图论算法的数学模型 引入:最短路的数学形式 最小割的数学形式 一些没用的总结 图论算法的数学模型 今天听敦敦敦的课总结一下... 前置芝士:网络流,最小割 引入:最短路的数学形式 松弛操作: 对于一条边\((u,v,w)\),\(\text {if}~(dis_u+w(u,v)<dis_v)~\text{then}~dis_v=dis_u+w(u,v)\) 所以对于求出来的dis,有\(dis_v\leq dis_u+w(u,v)\)对吧... 那么这和差分约束中\(x_i-x_j\leq

图论算法之DFS与BFS

概述(总) DFS是算法中图论部分中最基本的算法之一.对于算法入门者而言,这是一个必须掌握的基本算法.它的算法思想可以运用在很多地方,利用它可以解决很多实际问题,但是深入掌握其原理是我们灵活运用它的关键所在. 含义特点 DFS即深度优先搜索,有点类似广度优先搜索,也是对一个连通图进行遍历的算法.它的思想是从一个顶点V0开始,沿着一条路一直走到底,如果发现不能到达目标解,那就返回到上一个节点,然后从另一条路开始走到底,这种尽量往深处走的概念即是深度优先的概念. 由于用到递归,当节点特别多且深度很大