zoukankan      html  css  js  c++  java
  • SSLZYC 1763 观光旅游

    题目大意:
    求一个图的最小环。


    思路:
    完全模板题。
    思路一:直接用弗洛伊德,再加上一个判断是否有环的语句就可以了。

    思路二:用dij,枚举每条边,将该边删除,再求该边的两个端点之间的最短路,最短路再加上这条边,就是一个环。


    代码:

    弗洛伊德:

    #include <cstdio>
    #include <iostream>
    using namespace std;
    
    const int maxn=99999999;
    int a[101][101],n,m,b[101][101],ans,x,y,o;
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
         for (int j=1;j<=n;j++)
          a[i][j]=b[i][j]=maxn;  //初始化
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            scanf("%d",&o);
            a[x][y]=a[y][x]=b[x][y]=b[y][x]=o;  //无向图
        } 
        ans=99999999;
        for (int k=1;k<=n;k++)
        {
            for (int i=1;i<=n;i++)
             for (int j=1;j<=n;j++)
               if(i!=j&&j!=k&&i!=k) ans=min(ans,b[i][j]+a[j][k]+a[k][i]);  //求最小环
            for (int i=1;i<=n;i++)
             for (int j=1;j<=n;j++)
               b[i][j]=min(b[i][j],b[i][k]+b[k][j]);  //弗洛伊德
        }
        if (ans!=99999999) printf("%d\n",ans);
         else printf("No solution\n");
        return 0;
    }

    dij:

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    const int maxn=99999999;
    int x[10001],y[10001],a[101][101],b[101],c[101];
    int m,n,l,minn,o,ans;
    
    int main()
    {
        scanf("%d%d",&n,&m);
        ans=2147483647;
        for (int i=1;i<=n;i++)
         for (int j=1;j<=n;j++)
          a[i][j]=maxn;  //初始化
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d",&x[i],&y[i]);
            scanf("%d",&a[x[i]][y[i]]);
            a[y[i]][x[i]]=a[x[i]][y[i]];
        }   
        for (int k=1;k<=m;k++)
        {
            l=a[x[k]][y[k]];
            a[x[k]][y[k]]=maxn;  //删边
            memset(b,0,sizeof(b));
            b[x[k]]=1;
            for (int i=1;i<=n;i++)
             if (i!=x[k]) c[i]=a[x[k]][i];   //dij初始化
            for (int i=1;i<n;i++)
            {
                minn=maxn;
                for (int j=1;j<=n;j++)
                 if (b[j]==0&&c[j]<minn)  //求距离集合最近的点
                 {
                    minn=c[j];  
                    o=j;
                 }
                if(o==0) break;  
                b[o]=1;  //进入集合
                for (int j=1;j<=n;j++)
                 if (b[j]==0&&c[j]>c[o]+a[o][j])
                  c[j]=c[o]+a[o][j];  //重新计算最短路
            }
            a[x[k]][y[k]]=l;
            if (l+c[y[k]]<ans) ans=l+c[y[k]];  //判断答案
        }
        if(ans<maxn) printf("%d",ans);
         else puts("No solution");
        return 0;
    }
  • 相关阅读:
    03:矩形分割 (二分)
    09:膨胀的木棍 (二分+角度计算)
    A Cubic number and A Cubic Number (二分) HDU
    B
    08:不重复地输出数 (set)
    10:河中跳房子 (二分)
    07:和为给定数 (二分)
    04:网线主管 (二分)
    河中跳房子
    010:输出前k大的数
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998887.html
Copyright © 2011-2022 走看看