zoukankan      html  css  js  c++  java
  • 图的最小环(Floyd算法)

    题目:

      给出一个有向图,求它的最小环。

      有向图的环应至少含2个顶点,而无向图的一个环至少含3个顶点。

    简述:

      如果熟悉floyd算法的原理,那么便知道,每次循环都是由最外层的k去松弛点与点之间的距离的,那么对于当前dis[i][j]还未加入k进行松弛,如果有dis[i][j]+map[i][k]+map[k][j]<mincircle,那么此时的i与j的路径和k便形成了一个最小环,然后加入k进行松弛,求下一次能否通过其他点进行松弛而得到最小环,注意求最小环的时候要每更新一个,便求一次路径,不能等到最后才求,,原因是最后的pre数组与当前并不一致。

    无向图代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<vector>
     5 #include<queue>
     6 #include<cstring>
     7 #include<algorithm>
     8 #define numm ch-48
     9 #define pd putchar(' ')
    10 #define pn putchar('
    ')
    11 #define pb push_back
    12 #define debug(args...) cout<<#args<<"->"<<args<<endl
    13 #define bug cout<<"************"
    14 using namespace std;
    15 template <typename T>
    16 void read(T &res) {
    17     bool flag=false;char ch;
    18     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
    19     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
    20     flag&&(res=-res);
    21 }
    22 template <typename T>
    23 void write(T x) {
    24     if(x<0) putchar('-'),x=-x;
    25     if(x>9) write(x/10);
    26     putchar(x%10+'0');
    27 }
    28 typedef long long ll;
    29 const int maxn=110+10;
    30 const int maxm=50010;
    31 const int inf=0x3f3f3f3f;
    32 const int mod=1e9+7;
    33 int a[maxn][maxn],dis[maxn][maxn],pre[maxn][maxn];
    34 vector<int>ans;
    35 bool floyed(int n) {    ///判最小环
    36     int mircle=inf;
    37     bool flag=false;
    38     for(int k=1;k<=n;k++) {
    39         for(int i=1;i<k;i++)
    40             for(int j=i+1;j<k;j++) {    ///如果环需要至少包含3个点,则i!=j!=k
    41                 if(dis[i][j]!=inf&&a[i][k]!=inf&&a[k][j]!=inf) {///找到一个,便更新一次
    42                     if(mircle>dis[i][j]+a[i][k]+a[k][j]) {
    43                         mircle=dis[i][j]+a[i][k]+a[k][j];
    44                         flag=true;
    45                         ans.clear();
    46                         ans.push_back(k);
    47                         ans.push_back(j);
    48                         int d=j;
    49                         do {
    50                             d=pre[i][d];
    51                             ans.push_back(d);
    52                         }while(d!=i);
    53                     }
    54                 }
    55             }
    56         for(int i=1;i<=n;i++) { ///如果环需要至少包含3个点,则i!=j!=k
    57             if(i!=k)
    58                 for(int j=1;j<=n;j++) {
    59                     if(i!=j&&j!=k&&dis[i][k]!=inf&&dis[k][j]!=inf) {
    60                         if(dis[i][j]>dis[i][k]+dis[k][j]) {
    61                             dis[i][j]=dis[i][k]+dis[k][j];
    62                             pre[i][j]=pre[k][j];    ///attention!!!
    63                         }
    64                     }
    65                 }
    66         }
    67     }
    68     return flag;
    69 }
    70 int main()
    71 {
    72     int m,n;
    73     read(n),read(m);
    74     memset(a,inf,sizeof(a));
    75     memset(dis,inf,sizeof(dis));
    76     for(int i=1;i<=n;i++) {
    77         for(int j=1;j<=n;j++)
    78             pre[i][j]=i;
    79     }
    80     for(int i=1;i<=m;i++) {
    81         int u,v,w;
    82         read(u),read(v),read(w);
    83         a[u][v]=a[v][u]=dis[u][v]=dis[v][u]=w;
    84     }
    85     if(floyed(n)) {
    86         for(int i=0;i<ans.size();i++)
    87             write(ans[i]),pd;
    88         pn;
    89     }
    90     else puts("No solution.");
    91     return 0;
    92 }
    View Code

    有向图代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<vector>
     5 #include<queue>
     6 #include<cstring>
     7 #include<algorithm>
     8 #define numm ch-48
     9 #define pd putchar(' ')
    10 #define pn putchar('
    ')
    11 #define pb push_back
    12 #define debug(args...) cout<<#args<<"->"<<args<<endl
    13 #define bug cout<<"************"
    14 using namespace std;
    15 template <typename T>
    16 void read(T &res) {
    17     bool flag=false;char ch;
    18     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
    19     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
    20     flag&&(res=-res);
    21 }
    22 template <typename T>
    23 void write(T x) {
    24     if(x<0) putchar('-'),x=-x;
    25     if(x>9) write(x/10);
    26     putchar(x%10+'0');
    27 }
    28 typedef long long ll;
    29 const int maxn=2010+10;
    30 const int maxm=50010;
    31 const int inf=0x3f3f3f3f;
    32 const int mod=1e9+7;
    33 int a[maxn][maxn],dis[maxn][maxn],pre[maxn][maxn];
    34 int que[maxn+100],cnt;
    35 bool floyed(int n) {    ///有向图判最小环
    36     int mincircle=inf;
    37     bool flag=false;
    38     for(int k=1;k<=n;k++) {
    39         for(int i=1;i<=n;i++) {
    40             if(a[k][i]==inf||a[k][i]>mincircle) continue;
    41             for(int j=1;j<=n;j++) {
    42                 if(i==k&&j==k) continue;
    43                 if(dis[i][j]!=inf&&a[j][k]!=inf) {
    44                     if(mincircle>dis[i][j]+a[j][k]+a[k][i]) {
    45                         mincircle=dis[i][j]+a[j][k]+a[k][i];
    46                         flag=true;
    47                         cnt=0;
    48                         que[++cnt]=k;
    49                         que[++cnt]=j;
    50                         int d=j;
    51                         do {
    52                             d=pre[i][d];
    53                             if(d!=j&&d!=k)
    54                                 que[++cnt]=d;
    55                         }while(d!=i);
    56 
    57                     }
    58                 }
    59             }
    60         }
    61         for(int i=1;i<=n;i++) {
    62             if(dis[i][k]==inf) continue;
    63             for(int j=1;j<=n;j++) {
    64                 if(i==k&&j==k) continue;
    65                 if(dis[k][j]!=inf) {
    66                     if(dis[i][j]>dis[i][k]+dis[k][j]) {
    67                         dis[i][j]=dis[i][k]+dis[k][j];
    68                         pre[i][j]=pre[k][j];
    69                     }
    70                 }
    71             }
    72         }
    73     }
    74     return flag;
    75 }
    76 int main()
    77 {
    78     int m,n;
    79     read(n),read(m);
    80     memset(a,inf,sizeof(a));
    81     memset(dis,inf,sizeof(dis));
    82     for(int i=1;i<=n;i++) {
    83         a[i][i]=dis[i][i]=0;
    84         for(int j=1;j<=n;j++)
    85             pre[i][j]=i;
    86     }
    87     for(int i=1;i<=m;i++) {
    88         int u,v,w;
    89         read(u),read(v),read(w);
    90         a[u][v]=dis[u][v]=min(w,a[u][v]);
    91     }
    92     if(floyed(n)) {
    93         for(int i=cnt;i;i--)
    94             write(que[i]),pd;
    95         pn;
    96     }
    97     else puts("No solution.");
    98     return 0;
    99 }
    View Code

     

  • 相关阅读:
    样条之CatmullRom
    分形之树(Tree)
    B样条
    样条之贝塞尔(Bezier)
    插值与样条
    windows 下的Python虚拟环境(vitrualen)pycharm创建Django项目
    VS2010专业版和旗舰版(中文版)下载
    PHP课程环境安装总结文档
    原码、反码、补码知识详细讲解(此作者是我找到的讲的最细最明白的一个)
    C语言中size_t类型详细说明【转载】
  • 原文地址:https://www.cnblogs.com/wuliking/p/11584309.html
Copyright © 2011-2022 走看看