Silver Cow Party

One cow from each of N farms (1 ≤ N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ X ≤ N). A total of M (1 ≤ M≤ 100,000) unidirectional (one-way roads connects pairs of farms; road i requiresTi (1 ≤ Ti ≤ 100) units of time to traverse.

Each cow must walk to the party and, when the party is over, return to her farm. Each cow is lazy and thus picks an optimal route with the shortest time. A cow's return route might be different from her original route to the party since roads are one-way.

Of all the cows, what is the longest amount of time a cow must spend walking to the party and back?

Input
Line 1: Three space-separated integers, respectively:  NM, and  X 
Lines 2..  M+1: Line  i+1 describes road  i with three space-separated integers:  Ai, Bi, and  Ti. The described road runs from farm  Ai to farm  Bi, requiring  Ti time units to traverse.
Output
Line 1: One integer: the maximum of time any one cow must walk.
Sample Input
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
Sample Output
10
Hint
Cow 4 proceeds directly to the party (3 units) and returns via farms 1 and 3 (7 units), for a total of 10 time units.


题意:

    给N个牧场,每个牧场里有一头牛,他们都要到第X个牛的牧场里聚会,然后返回各自的牧场,给定M组数据,代表从x到y牧场所用的时间(有向),问来回时间最长的牛所花费的时间,都是走最短路径;

思路:

    刚开始暴力了一波,求了n次的最短路,结果超时了(QAQ理所当然!),问了下 dalao 才知道先求从x到各个农场的最短路dir【】,然后将有向图map【】【】的对称值交换一下,即map【i】【j】=map【j】【i】;因为是有向图,原本从各牧场x的路径是dis【i】【x】,原本是从1到2有路,求从1(i)到2(x)的路径,现在换成从2到1有路,求从2(x)到1(i)的路径,仔细想想是不是一样的呢?(重要!!!)所以交换后,再从x处出发,到达各牧场的路径和从 原本各牧场出发到x的路径是一样的;即求得dis【x】【i】,在遍历n个点,求dir+dis的最大值!

图示:


这是一个有向图,正常暴力的话是求从各顶点到2号顶点的距离(红色),然后调换后(蓝色)(还是原本的有向图,不过是将以前起点,终点互换),路还是以前的路,只是起点和终点换了一下而已。

代码如下:

#include<cstdio>
#include<cstring>
#define inf 0x3f3f3f3f
int map[1010][1010],dis[1010],dir[1010],book[1010];
int main()
{
	int n,m,t,i,j,k,p;
	while(~scanf("%d%d%d",&n,&m,&t))
		{
			for(i=1; i<=n; i++)     //初始化
				for(j=1; j<=n; j++)
					if(i==j)map[i][j]=0;
					else map[i][j]=map[j][i]=inf;
			for(i=1; i<=m; i++)  //有向图输入
				{
					int a,b,c;
					scanf("%d%d%d",&a,&b,&c);
					if(map[a][b]>c)
						map[a][b]=c;
				}
            //求t到个牧场的最短路 dir【】
			for(i=1; i<=n; i++)
				dir[i]=map[t][i];
			memset(book,0,sizeof(book));
			book[t]=1;
			for(i=1; i<=n; i++)
				{
					int minn=inf;
					for(j=1; j<=n; j++)
						{
							if(!book[j]&&dir[j]<minn)
								{
									k=j;
									minn=dir[j];
								}
						}
					if(minn==inf)break;
					book[k]=1;
					for(j=1; j<=n; j++)
						{
							if(!book[j]&&dir[j]>minn+map[k][j])
								{
									dir[j]=minn+map[k][j];
								}

						}
				}

			for(i=1; i<=n; i++)   //交换地图的对称值,map[i][j]=map[j][i]
				for(j=i+1; j<=n; j++)
					{
						int tt=map[i][j];
						map[i][j]=map[j][i];
						map[j][i]=tt;
					}

			for(i=1; i<=n; i++)  //重新求t到各牧场的最短距离,即去聚会时各牛用的时间
				dis[i]=map[t][i];
			memset(book,0,sizeof(book));
			book[t]=1;
			for(i=1; i<=n; i++)
				{
					int minn=inf;
					for(j=1; j<=n; j++)
						{
							if(!book[j]&&dis[j]<minn)
								{
									k=j;
									minn=dis[j];
								}
						}
					if(minn==inf)break;
					book[k]=1;
					for(j=1; j<=n; j++)
						{
							if(!book[j]&&dis[j]>minn+map[k][j])
								dis[j]=minn+map[k][j];
						}
				}
				
			int maxx=-1;
			for(i=1; i<=n; i++)  //打擂台法,求 来(dis)回(dir)的和最大的值
				if(dis[i]+dir[i]>maxx)
					maxx=dis[i]+dir[i];
			printf("%d\n",maxx);
		}
}

猜你喜欢

转载自blog.csdn.net/qq_41890797/article/details/80615749