首页 > 代码库 > 【总结】图论算法

【总结】图论算法

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--;    } 

 

【总结】图论算法