SSL-ZYC 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;
}
posted @ 2018-03-15 16:21  全OI最菜  阅读(65)  评论(0编辑  收藏  举报