19北邮计算机-C 城市道路 //最短路径

时间限制 1000 ms 内存限制 65536 KB

题目描述

计算从城市1到城市n的最短路径长度。分为白天和黑夜,黑夜会关掉若干条线路,分别计算城市1到城市n的在白天和黑夜的最短路径长度。保证每个城市与其他城市必有连接。两个城市之间可能有多条路。

输入格式
第一行为数据组数T
对于每组测试数据

第一行三个整数,n,m,k. (1<=n<=50)n表示城市个数,m表示道路个数,k表示黑夜需要关闭的道路个数。

接下来m行,每行 三个整数 x,y,c (1<=x,y<=n),其中第 i 行(1<=i <=m)表示第 i 条道路为从城市x到城市y长度为c(可能存在重复边)。

接下来k行,每行一个整数w,表示黑夜要关闭的道路编号。

输出格式
每组数据输出两行

第一行为白天从城市1到城市n的最短距离

第二行为黑夜从城市1到城市n的最短距离

输入样例

2
4 4 1
1 2 1
2 3 1
3 4 1
1 4 1
4
4 5 1
1 2 1
2 3 2
3 4 3
1 3 1
1 4 7
4

 输出样例

1
3
4
6

代码1://Floyed弗洛伊德实现,因为n<=50,O(n^3)不会超时

#include<bits/stdc++.h>
using namespace std;
struct B
{
	int x,y,c;
}b[1003];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,m,k,i,j,w,x,y,c;
		int d1[53][53],d2[53][53];
		memset(d1,-1,sizeof(d1));//最大值用-1表示 若用0x7f表示 可能与另一个整数相加超出int的最大值 得到负值 则导致出错 
		memset(d2,-1,sizeof(d2));//或是存储路径用long long数组 然后用memset(d,0x7f,sizeof(d));初始化 
		scanf("%d%d%d",&n,&m,&k);
		for(i=1;i<=m;++i)
		{
			scanf("%d%d%d",&x,&y,&c);
			b[i].x=x;
			b[i].y=y;
			b[i].c=c;
			if(d1[x][y]==-1)
			{
				d1[x][y]=d1[y][x]=c;
			}
			else if(d1[x][y]>c)
			{
				d1[y][x]=d1[x][y]=c;
			}
		}
		for(i=0;i<k;++i)
		{
			scanf("%d",&w);
			b[w].x=b[w].y=b[w].c=-1;
		}
		for(i=1;i<=m;++i)
		{
			
			if(b[i].x!=-1)
			{
				x=b[i].x;
				y=b[i].y;
				c=b[i].c;
				if(d2[x][y]==-1)
				{
					d2[x][y]=d2[y][x]=c;
				}
				else if(d2[x][y]>c)
				{
					d2[x][y]=d2[y][x]=c;
				}
			}
			
		}
		//Floyed弗洛伊德 
		for(int z=1;z<=n;++z)
		{
			for(i=1;i<=n;++i)
			{
				for(j=1;j<=n;++j)
				{
					if(d1[i][z]!=-1&&d1[z][j]!=-1)
					{
						if(d1[i][j]!=-1)
						d1[i][j]=min(d1[i][j],d1[i][z]+d1[z][j]);
						else d1[i][j]=d1[i][z]+d1[z][j];
					}
					if(d2[i][z]!=-1&&d2[z][j]!=-1)
					{
						if(d2[i][j]!=-1)
						d2[i][j]=min(d2[i][j],d2[i][z]+d2[z][j]);
						else d2[i][j]=d2[i][z]+d2[z][j];
					}
				}
			}
		}
		printf("%d\n%d\n",d1[1][n],d2[1][n]);
	}
} 

代码2: //Dijkstra迪杰斯特拉 

#include<bits/stdc++.h>
using namespace std;
struct B
{
	int x,y;
	long long c;
}b[1003];
int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		int n,m,k,i,j,w,x,y,z[53];
		long long c,d1[53][53],d2[53][53],dis1[53],dis2[53];
		memset(d1,0x7f,sizeof(d1));//最大值用-1表示 若用0x7f表示 可能与另一个整数相加超出int的最大值 得到负值 则导致出错 
		memset(d2,0x7f,sizeof(d2));//或是存储路径用long long数组 然后用memset(d,0x7f,sizeof(d));初始化 
		memset(dis1,0x7f,sizeof(dis1));
		memset(dis2,0x7f,sizeof(dis2));
		
		scanf("%d%d%d",&n,&m,&k);
		for(i=1;i<=m;++i)
		{
			scanf("%d%d%lld",&x,&y,&c);
			b[i].x=x;
			b[i].y=y;
			b[i].c=c;
			d1[x][y]=d1[y][x]=min(c,d1[x][y]);
			
		}
		for(i=0;i<k;++i)
		{
			scanf("%d",&w);
			b[w].x=b[w].y=b[w].c=-1;
		}
		for(i=1;i<=m;++i)
		{
			
			if(b[i].x!=-1)
			{
				x=b[i].x;
				y=b[i].y;
				c=b[i].c;
				d2[x][y]=d2[y][x]=min(c,d2[x][y]);
			}	
		}
		//Dijkstra迪杰斯特拉 
		for(i=2;i<=n;++i)
		{
			dis1[i]=d1[1][i];
			dis2[i]=d2[1][i];
		}
		memset(z,0,sizeof(z));
		z[1]=1;
		for(i=1;i<n;++i)
		{
			int mi=0x7fffffff,z1=-1;
			for(j=2;j<=n;++j)
			{
				if(!z[j]&&dis1[j]<mi)
				{
					mi=dis1[j];
					z1=j;
				}
			}
			if(z1!=-1)
			{
				z[z1]=1;
				dis1[z1]=mi;
				if(z1==n)break;
				for(j=2;j<=n;++j)
				{
					if(!z[j])
					{
						dis1[j]=min(dis1[j],mi+d1[z1][j]);
					}
				}
			}
		}
		printf("%lld\n",dis1[n]);
		
		memset(z,0,sizeof(z));
		z[1]=1;
		for(i=1;i<n;++i)
		{
			int mi=0x7fffffff,z2=-1;
			for(j=2;j<=n;++j)
			{
				if(!z[j]&&dis2[j]<mi)
				{
					mi=dis2[j];
					z2=j;
				}
			}
			if(z2!=-1)
			{
				z[z2]=1;
				dis2[z2]=mi;
				if(z2==n)break;
				for(j=2;j<=n;++j)
				{
					if(!z[j])
					{
						dis2[j]=min(dis2[j],mi+d2[z2][j]);
					}
				}
			}
		}
		printf("%lld\n",dis2[n]);
	}
}
		

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值