zoukankan      html  css  js  c++  java
  • 【总结】图论算法

    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:
    ",k);  //cout<<"Case #"<<k<<":"<<endl;
                   printf("The minimal distance is: %.2f
    ",sum);  //输出sum
                   cin>>n;
                   if(n != 0) printf("
    ");}}

    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
    ",sum);
              cin>>n;
              if(n!=0)     printf("
    "); }}

    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--;    } 
  • 相关阅读:
    MySQL中IS NULL、IS NOT NULL、!=不能用索引?胡扯!
    市值TOP10,人类进化及中美坐标
    倒序切片
    对list进行切片
    Python之定义可变参数
    Python之递归函数
    Python之“可变”的tuple
    Python之创建单元素tuple
    Python中Unicode字符串
    Pycharm配置autopep8让Python代码更符合pep8规范
  • 原文地址:https://www.cnblogs.com/KID-XiaoYuan/p/6414774.html
Copyright © 2011-2022 走看看