pta a.1003 的收获

pta a.1003 的收获

题目

在这里插入图片描述

对于题目的收获

这是英文的题目,在这里面我犯的错有两个

  1. 我在模型提炼的时候把题目中的路搞成了有向图,这个是非常荒谬的。在没有说明的情况下,路一定是无向图。
  2. 最后的输出第一个要的是:the number of different shortest paths between c1 and c2 也就是不同最短路径的条数。

思路

其实通过题目一下子就可以看出这是最短路径的一个模型应用,只不过在上面加入了最短路径条数和点权的问题。

解决

首先是最短路径,这里用的是dijkstra

const int MAXN=510;
const int INF=100000000;
int GM[MAXN][MAXN];
int visit[MAXN];
int dis[MAXN];
int num[MAXN];
int n,m,c1,c2;
void myfunc(int s);
struct node{
	int self;
	int sum;
};
node weight[MAXN];
void myfunc(int s)
{
	dis[s]=0;
	weight[s].sum=weight[s].self;  
	num[s]=1;
	int x;
	int MIN;
	for(int k=0;k<n;k++)
	{
		x=-1;
		MIN=INF;
		for(int i=0;i<n;i++)
		{
			if(visit[i]==false&&dis[i]<MIN)
			{
				x=i;
				MIN=dis[i];
			}
			
		}
		if(x==-1)return;//没找到说明顶点与剩下的不连通直接退
		visit[x]=true;
		for(int i=0;i<n;i++)
		{
			if(visit[i]==false&&GM[x][i]!=INF)
			{
				if(dis[i]>dis[x]+GM[x][i])
				{
					dis[i]=dis[x]+GM[x][i];
					weight[i].sum=weight[i].self+weight[x].sum; 
					num[i]=num[x];
					 
					
				}
				else if(dis[i]==dis[x]+GM[x][i]   )
				{
					if(weight[i].sum<weight[i].self+weight[x].sum)
					{
						weight[i].sum=weight[i].self+weight[x].sum;
					   }
					num[i]+=num[x];   
					
				}
				
			}
		}
	}

	
}

收获

  1. 对于图来讲,不连通的表示方式是设一个INF这个值,还是有所讲究的。第一是要够大,所以胡凡推荐了两个 1000000000 也就是1e9还有就是0x3fffffff,但是不要太大,因为常有两个边相加如果二者加和超过了int的范围就会出错比如0x7fffffff。
  2. 由于算法要求的一步步的纳入,所以要区分已纳入和未纳入。由此就有了visit[]数组。这一点我还是有一个疑惑,也就是这个算法是不是贪心算法的具体体现,书上没说,我也不太清楚,留到以后解决。
  3. 关于两个变动,原来的算法因为只求最短距离,所以距离相等时是不做任何处理的。但是这里不行,因为我们要求最短的条数和点权最大的路,所以要在用中介调整距离的时候调整一下。下面两条就是说这个的。
  4. 首先是最短的条数
   for(int i=0;i<n;i++)
   	{
   		if(visit[i]==false&&GM[x][i]!=INF)
   		{
   			if(dis[i]>dis[x]+GM[x][i])
   			{
   				dis[i]=dis[x]+GM[x][i];
   				
   				num[i]=num[x];//1
   				 
   				
   			}
   			else if(dis[i]==dis[x]+GM[x][i]   )
   			{
   				
   				num[i]+=num[x];//2
   				
   			}
   			
   		}
   	}

一共两条改动,1的那里因为最短就是通过中介直达,所以条数和通过中介的一样多。2的那里是由于路程是并列的,所以他们都是最短路径所以相加。
5. 然后是最大权值
先写一个数据结构

struct node{
	int self;
	int sum;
};

这个数据结构比较关键(两个数组也行就没那么直观了)
self就是存的他本来的权值(题目里的救援队的数量)
sum是从起点到这里的目前最短路径的救援队数量的总和

		for(int i=0;i<n;i++)
		{
			if(visit[i]==false&&GM[x][i]!=INF)
			{
				if(dis[i]>dis[x]+GM[x][i])
				{
					dis[i]=dis[x]+GM[x][i];
					weight[i].sum=weight[i].self+weight[x].sum; //1
					
					 
					
				}
				else if(dis[i]==dis[x]+GM[x][i]   )
				{
				//2
					if(weight[i].sum<weight[i].self+weight[x].sum)
					{
						weight[i].sum=weight[i].self+weight[x].sum;
					   }
					
					
				}
				
			}
		}

1的这里十分易于理解,就是发现一条新的最短路径到这里就把这里的权值加上上一个的总和.2这里 weight[i].self+weight[x].sum 是新的总权值和已有的权值作比较要是原有的小就要更新

6.这个是我对dijkstra算法的一个小的要求就是在设置dis[]数组的时候把起点设为0其他设为INF,然后让程序找到起点作为第一个中介点去执行操作,这样在进行如4 5的操作才能不用去特殊照顾第一个中介点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值