SSL_1763 观光旅游

题意:

    求一个图的最小环。

思路:

    我们可以用floyd求也可以用dijkstra求,这里我两种方法都用了。

代码:

floyd

#include<cstdio>
#include<cstring>
int n,m,f[501][501],dis[501][501],a,b,c,ans;
int min(int x,int y){return x>y?y:x;}
int main()
{
	for (int i=1;i<=500;i++)
	  for (int j=1;j<=500;j++)
          f[i][j]=dis[i][j]=99999999;
	
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&a,&b,&c);
		dis[a][b]=f[a][b]=c;
		dis[b][a]=f[b][a]=c;
	}
	ans=2100000000;
	for (int k=1;k<=n;k++)//边做floyd边求最小环
	{
		for (int i=1;i<=n;i++)
		    for (int j=i+1;j<=n;j++)//i和j这里可以1~k-1,但1~n也没关系
		        if (dis[i][j]!=99999999&&f[j][k]!=99999999&&f[k][i]!=99999999)ans=min(ans,dis[i][j]+f[j][k]+f[k][i]);//dis[i][j]为i到j的最小距离
	    for (int i=1;i<=n;i++)                                           //f[i][j]表示i到j这条边的长度,这样加起来就是一个环
	        for (int j=1;j<=n;j++)
	            dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);//floyd
	}
	if (ans==2100000000) printf("No solution");else
	printf("%d",ans);
}

dijkstra

#include"cstdio"
#include"cstring"
int ans,k,min1,p,q,c[501],f[501][501],n,m,x,y,z,b[501];
int min(int x,int y) {return x>y?y:x;}
void dijkstra(int x,int y)
{
	memset(b,0,sizeof(b));
	for (int i=1;i<=n;i++) c[i]=f[x][i];
	b[x]=1;c[x]=0;
	for (int i=1;i<n;i++)
	{
		min1=99999999;
		k=0;
		for (int j=1;j<=n;j++)
		    if ((!b[j])&&(c[j]<min1))
		    {
		    	min1=c[j];
		    	k=j;
		    }
		if (k==0) break;
		b[k]=true;
		for (int j=1;j<=n;j++)
		    if (c[k]+f[k][j]<c[j]) c[j]=c[k]+f[k][j];
	}	
}

int main()
{
	scanf("%d%d",&n,&m);//dijkstra就是把i到j的边去掉,再用dijkstra求i到j的最小距离,再加上原来i到j的距离我们就可以形成了一个环,
	memset(f,127/3,sizeof(f));//floyd比这个算法快
	while (m--)
	{
		scanf("%d%d%d",&x,&y,&z);
		f[x][y]=f[y][x]=z;
	}
	ans=99999999;
	for (int i=1;i<=n;i++)
	    for (int j=i+1;j<=n;j++)
	    {
	    	int temp=f[i][j];
	    	f[j][i]=f[i][j]=99999999;//去掉边
	    	dijkstra(i,j);//求最短距离
	    	f[j][i]=f[i][j]=temp;//还原
	    	ans=min(ans,c[j]+temp);//记录最小值
	    }
	if(ans==99999999) printf("No solution");
	else 
	printf("%d",ans);
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值