洛谷 P3115 [USACO15JAN]牛路线Cow Routing

题目描述

Tired of the cold winter weather on her farm, Bessie the cow plans to fly to a warmer destination for vacation. Unfortunately, she discovers that only one airline, Air Bovinia, is willing to sell tickets to cows, and that these tickets are somewhat complicated in structure. Air Bovinia owns N planes (1 <= N <= 1000), each of which flies on a specific "route" consisting of two or more cities. For example, one plane might fly on a route that starts at city 1, then flies to city 5, then flies to city 2, and then finally flies to city 8. No city appears multiple times in a route. If Bessie chooses to utilize a route, she can board at any city along the route and then disembark at any city later along the route. She does not need to board at the first city or disembark at the last city. Each route has a certain cost, which Bessie must pay if she uses any part of the route, irrespective of the number of cities she visits along the route. If Bessie uses a route multiple times during her travel (that is, if she leaves the route and later comes back to use it from antoher city), she must pay for it each time it is used. Bessie would like to find the cheapest way to travel from her farm (in city A) to her tropical destination (city B). Please help her decide what is the minimum cost she must pay, and also the smallest number of individual flights she must use take to achieve this minimum cost.
 

输入

The first line of input contains A, B, and N, separated by spaces. The next 2N lines describe the available routes, in two lines per route. The first line contains the cost of using the route (an integer in the range 1..1,000,000,000), and the number of cities along the route (an integer in the range 1..100). The second line contains a list of the cities in order along the route. Each city is identified by an integer in the range 1..1000. Note that the cost of an itinerary can easily add up to more than can fit into a 32-bit integer, so you should probably use 64-bit integers (e.g., "long long" integers in C/C++).
 

输出

Output the minimum cost of an itinerary that Bessie can use to travel from city A to city B, as well as the minimum number of individual flights required to achieve this minimum cost. If there is no solution, output "-1 -1" (quotes for clarity) on a single line.
 

样例输入 

3 4 33 51 2 3 4 52 33 5 41 21 5

样例输出 

2 2

来源

USACO 2015 January Silver

题解:这题我看了几位dalao的题解,都没看懂……于是,我就开始硬撸啦(其实我这代码比较好理解,但是效率降低了不少,空间也增加了蛮多)。我们数据读进来,然后记录每两个点之间的最小值(已经去掉不少边啦),然后嘛,就用SPFA专配——first,next,v,w数组啦,还有,别忘记一点,点与点之间的距离不是1,而是通过航线计算得到的(害的我调了好久),最后嘛,SPFA一下,注意当距离一样时,但经过的点比原来少时,也是要更新滴,好了,知道了这些,我们便来码代码吧。

#include <cstdio>
#include <cstring>
#define N 2000005
int maxx,a,b,x,y,z[1005],n,aa[1005][1005],bb[1005][1005];
int cnt,first[N],next[N],v[N],w[N],ww[N];
int head,tail,q[N];
long long dis[1005][2];
bool vis[1005];
using namespace std;
inline int read()    
{    
    int f=1,x=0;    
    char ch=getchar();    
    if (ch=='-')    
    {    
        f=-1;    
        ch=getchar();    
    }    
    while ((ch<'0')||(ch>'9')) ch=getchar();    
    while ((ch>='0')&&(ch<='9'))    
    {    
        x=x*10+ch-48;    
        ch=getchar();    
    }    
    return f*x;    
}
inline void spfa(int x)
{
	for (int i=1;i<1005;i++) dis[i][0]=1000000000000;
	dis[x][0]=0;
	dis[x][1]=0;
	head=0;
	tail=1;
	q[1]=x;
	vis[x]=1;
	while (head<tail)
	{
		head++;
		vis[q[head]]=0;
		for (int i=first[q[head]];i;i=next[i])
		{
			int k=v[i];
			if (dis[k][0]>dis[q[head]][0]+w[i])
			{
				dis[k][0]=dis[q[head]][0]+w[i];
				dis[k][1]=dis[q[head]][1]+ww[i];
				if (!vis[k])
				{
					tail++;
					q[tail]=k;
					vis[k]=1;
				}
			} else
			if (dis[k][0]==dis[q[head]][0]+w[i])
			  if (dis[k][1]>dis[q[head]][1]+ww[i])
			    dis[k][1]=dis[q[head]][1]+ww[i];
		}
	}
	if (dis[b][0]==1000000000000)
	{
		printf("-1 -1\n");
		return;
	} else
	{
		printf("%lld %lld\n",dis[b][0],dis[b][1]);
		return;
	}
}
int main()
{
	memset(aa,0x3f3f3f3f,sizeof(aa));//赋大值
	a=read(),b=read(),n=read();
	for (int i=1;i<=n;i++)
	{
		x=read(),y=read();
		for (int j=1;j<=y;j++) 
		{
			z[j]=read();
			if (z[j]>maxx) maxx=z[j];//找到最大的城市编号
		}
		for (int j=1;j<=y;j++)
		  for (int k=j+1;k<=y;k++)
		    if (aa[z[j]][z[k]]>x) 
			{
				aa[z[j]][z[k]]=x;
				bb[z[j]][z[k]]=k-j;//记录下距离,但要注意不是k-j+1,因为第一个终点与第二个起点是同一个点
			}
	}
	for (int i=1;i<=maxx;i++)
	  for (int j=1;j<=maxx;j++)
	    if (aa[i][j]<0x3f3f3f3f)
	    {//建单向边
	    	next[++cnt]=first[i];
	    	first[i]=cnt;
	    	v[cnt]=j;
	    	w[cnt]=aa[i][j];
	    	ww[cnt]=bb[i][j];
	    }
	spfa(a);
	return 0;
} 

猜你喜欢

转载自blog.csdn.net/zhouhongkai06/article/details/80721272