Silver Cow Party (chemin le plus court à source unique: utilisation du côté à sens unique aller et retour le plus court)

Sujet 1: Soumettre le lien pour ce sujet. Ce sujet peut être écrit avec une matrice de contiguïté, avec peu de sommets.
Sujet 2: Soumettre le lien , ce sujet doit être écrit avec une liste de contiguïté, il y a trop de sommets

Une vache de chacune des N fermes (1 ≤ N ≤ 1000) numérotée de 1… N va assister à la grande fête des vaches qui se tiendra à la ferme #X (1 ≤ X ≤ N). Un total de M (1 ≤ M ≤ 100 000) unidirectionnels (des routes à sens unique relient des paires de fermes; la route i nécessite Ti (1 ≤ Ti ≤ 100) unités de temps pour traverser.

Chaque vache doit se rendre à la fête et, une fois la fête terminée, retourner dans sa ferme. Chaque vache est paresseuse et choisit ainsi un itinéraire optimal avec le temps le plus court. L'itinéraire de retour d'une vache peut être différent de son itinéraire d'origine vers la fête, car les routes sont à sens unique.

De toutes les vaches, quel est le temps le plus long qu'une vache doit passer à marcher pour se rendre à la fête et en revenir?


Ligne d' entrée 1: Trois entiers séparés par des espaces, respectivement: N, M et X
Lignes 2… M + 1: La ligne i + 1 décrit la route i avec trois entiers séparés par des espaces: Ai, Bi et Ti. La route décrite va de la ferme Ai à la ferme Bi, nécessitant la traversée des unités de temps Ti. Ligne de
sortie
1: Un entier: le temps maximum pendant lequel une vache doit marcher.

Exemple d'entrée

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

Exemple de sortie

dix

Indice La
vache 4 se rend directement au groupe (3 unités) et revient via les fermes 1 et 3 (7 unités), pour un total de 10 unités de temps.

Signification du titre:
n fermes, numérotées de 1 à n, maintenant chaque ferme envoie une vache à la fête qui se tient à la ferme x. Chaque vache est paresseuse et veut passer le moins de temps possible dans les deux sens (à quel point c'est court, bien sûr, cela prend moins de temps lorsque vous partez, et moins de temps lorsque vous revenez). Les besoins actuels sont hors de toutes les vaches. , et le coût total des allers-retours est Le temps passé par la vache avec le plus de temps
Remarque: Du côté à sens unique, la distance aller-retour peut ne pas être la même

Idée:
chemin le plus court de source unique, utilisez deux fois,
1. Trouvez d'abord le chemin le plus court du sommet x à chaque sommet
2. Ensuite, trouvez le chemin le plus court de chaque sommet à x (en fait, il vous suffit de retourner toutes les arêtes et de trouver le plus court x à chaque sommet à nouveau. Route)
Si vous ne comprenez pas le code: veuillez consulter le
code du livre de l'algorithme Aha

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int inf=0x3f3f3f3f;

int e[1100][1100];
int book[1100];//book[i]标记为1,说明顶点i到源点的最短路已确定,即dis[i]不可能更小的了,若book[i]标记仍为0,说明此刻的dis[i]还有可能变得更小。
int dis[1100];//用来存储源点到各个点的距离
int dis1[1100];
int n,m,x;
/* 
e[i][j]用来存储顶点i到顶点j的距离,
规定顶点i到其本身的距离为0,
规定顶点i不能直接到达顶点j的距离为无穷大

数组book,book[i]==1表示顶点i不得再被使用,
book[i]==0表示顶点i可以被使用 

数组dis1,用来存放x到各个点的最小距离
数组dis,用来存放各个点到x的最小距离

*/
void Dijkstra()
{
	int i,j;
	memset(book,0,sizeof(book));//全部是估计值
	book[x]=1;//x到x的距离最短 
	// 
	for(i=1;i<=n;i++)///最初dis数组中存放的是x直接到任意一个点的最小值,
		dis[i]=e[x][i];/而不是任意两点的最小值 

	int minn,u,v;
	for(i=1;i<=n-1;i++)//为什么这里最多循环为n-1次,那是因为源点到源点本身最短路肯定为0,剩下(n-1)个顶点到源点的距离才是我们要求的,而每一次循环我们一定确定一个顶点的最短路,为什么呢,看下面的解释
	{
		minn=inf;
		u=-1;
	
		for(j=1;j<=n;j++)//寻找离源点到最近的一个点 
		{
			if(!book[j]&&minn>dis[j])//book[j]==1表明dis[j]已经确定过了,是最短的
			{
				minn=dis[j];
				u=j;
			}
		}
		/*
       这里说说为什么找到了离源点最近的顶点u,就一定可以确定u到源点的最短路了,为什么不能再通过别的路使得源点到u的距离变的更短了,首先你要明白,我们每次都是寻找的就是离源点的最近的顶点,所以当然不可能存在比该路更短的路了。你还要明白,此刻的u不一定是和源点直接相连的顶点,有可能是了经过很多顶点才到达顶点u的,但无论经过多少顶点到达u的,这条源点到u的路一定是最短的,可以相当于贪心,每次都是寻找最短,最短从而得到最短
        */
		if(u==-1)
			break;
		/*
		这里为什么要加一个跳出循环的操作呢,那是因为,这里的(n-1)次循环我们其实假设的是源点一定可以到其它(n-1)个顶点(无论是直接到达,还是间接到达)。但有些样例可能存在源点永远不可能到达的顶点,假设只有n-5个顶点与源点相连,那么其实我们只循环n-5次就可以了,所以这里才会加一个提前跳出的操作
		*/
		book[u]=1;//dis[u]最短,不可能再小了
		for(v=1;v<=n;v++)//寻找与u相连的顶点v,利用顶点u,看是否可以使源点到v的距离更短,即能否使dis[v]更小
		{
			if(!(book[v]||e[u][v]<inf))//表明u与v有路,dis[v]有可能变小,或者,若book[v]==0,dis[v]也有可能变小。
			{
				if(dis[v]>dis[u]+e[u][v])//是否可使dis[v]更小
					dis[v]=dis[u]+e[u][v];
			}
		}
	}
}
int main()
{
	int i,j,u,v,w,t;
	while(~scanf("%d %d %d",&n,&m,&x))
	{
		for(i=1;i<=n;i++)
			for(j=1;j<=n;j++)
				if(i==j)	e[i][j]=0;
				else 		e[i][j]=inf;
		for(i=1;i<=m;i++)
		{
			scanf("%d %d %d",&u,&v,&w);
			e[u][v]=min(w,e[u][v]);//单向边,可能有重边 
		}
		Dijkstra();
	
		for(i=1;i<=n;i++)
			dis1[i]=dis[i];
	
		/*
		源点x到别的点的最短路已求出,
	
		因为是单向边,因此二者往返很可能不是一条路
		那该怎么求别的点到源点x的最短路
	
		只需将给出的边方向翻转再使用Dijkstra(x),仔细想想,因为原本可以走的路现在因为边翻转的缘故,已经不能走了,x若还想到达其它点,其实走的路便是其它点到x所走的路 
	
		*/ 
	
		for(i=1;i<=n;i++)
		{
			for(j=i+1;j<=n;j++)
			{
				t=e[i][j];//边翻转,不能覆盖 
				e[i][j]=e[j][i];
				e[j][i]=t;
			}
		}
		
		Dijkstra();
	
		int maxx=-inf;
		for(i=1;i<=n;i++)
			if(dis[i]<inf&&dis1[i]<inf)
				maxx=max(maxx,dis[i]+dis1[i]);
		printf("%d\n",maxx);
	}
	return 0;
}

Je suppose que tu aimes

Origine blog.csdn.net/Helinshan/article/details/109919967
conseillé
Classement