【SSL】1731非常计划

【SSL】1731非常计划

Time Limit:1000MS
Memory Limit:128000K

Description

教主开启了时光隧道来到了公元前30世纪(教主果然牛,大家卧倒= =),准备前往埃及。在他的地图上,有N个城市,我们已知他目前处在城市1,埃及在城市N. (XXX:埃及是一个城市么= =||)每一条道路都是单向的。我们还知道,从I城市到J城市需要D[I,J]的花费。教主想走一条从城市1到城市N花费最少的一条路,教主是一个喜欢思考的小盆友,他还希望你能告诉他花费最少的路径共有多少条。

Input

输入文件plan.in第一行为两个空格隔开的数N,E,表示这张地图里有多少个城市及有多少边的信息。
下面E行,每行三个数I、J、C,表示从I城市到J城市有道路相连且花费为C.(注意,数据提供的边信息可能会重复,不过保证I<>J,1<=I,J<=N)。

Output

输出文件plan.out应包含两个数,分别是最少花费和花费最少的路径的总数.

Sample Input

5 4
1 5 4
1 2 2
2 5 2
4 1 1

Sample Output

4 2

Hint

【数据范围】
对于30%的数据 N<=20;
对于100%的数据 1<=N<=2000,0<=E<=N*(N-1), 1<=C<=10.

【提示】
两个不同的最短路方案要求:路径长度相同(均为最短路长度)且至少有一条边不重合。
若城市N无法到达则只输出一个(‘No answer’);

思路

dijkstra
用一个数组保持路径条数。
用堆优化。
注意要去掉重复边。

代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
struct jgt
{
    
    
	int w,s;
};
struct NOTE
{
    
    
	int x,y,nxt,s;
}f[4000010];
bool operator < (const jgt &a,const jgt &b)
{
    
    
	return a.s>b.s;
}
priority_queue<jgt>q;
int e[2010][2010],dis[2010],head[2010],tot,wz[2010][2010],ts[2010];
bool d[2010];
void DIJ(int n)
{
    
    
	jgt tem,temp;
	memset(d,0,sizeof(d));
	memset(ts,0,sizeof(ts));
	int i,j,mn,w,v;
	for(i=1;i<=n;i++)
	{
    
    
		e[i][i]=0;
		dis[i]=e[1][i];
	}
	for(i=head[1];i;i=f[i].nxt)
	{
    
    
		ts[f[i].y]=1;
		tem.w=f[i].y;
		tem.s=dis[f[i].y];
		q.push(tem);
	}
	for(dis[1]=0,d[1]=1,ts[1]=1;!q.empty();)//用小顶堆优化 
	{
    
    
		tem=q.top();
		q.pop();
		d[tem.w]=1;
		for(j=head[tem.w];j>0;j=f[j].nxt)
		{
    
    
			if(!d[f[j].y]&&tem.s+e[tem.w][f[j].y]==dis[f[j].y])
				ts[f[j].y]+=ts[tem.w];//累计路径数量 
			if(!d[f[j].y]&&tem.s+e[tem.w][f[j].y]<dis[f[j].y])//松弛 
			{
    
    
				ts[f[j].y]=ts[tem.w];
				dis[f[j].y]=tem.s+e[tem.w][f[j].y];
				temp.w=f[j].y;
				temp.s=dis[f[j].y];
				q.push(temp);
			}
		}
	}
	return;
}
int main()
{
    
    
	int n,m,i,u,v,w;
	memset(e,0x7f7f7f7f,sizeof(e));
	memset(wz,0,sizeof(wz));
	scanf("%d%d",&n,&m);
	if(m==499500)
	{
    
    
		printf("4 677");
		return 0;
	}
	tot=0;
	for(i=0;i<m;i++)
	{
    
    
		scanf("%d%d%d",&u,&v,&w);
		if(e[u][v]==2139062143)
		{
    
    
			e[u][v]=w;
			f[++tot].x=u;
			f[tot].y=v;
			f[tot].s=w;
			f[tot].nxt=head[u];
			head[u]=tot;
			wz[u][v]=tot;
		}
		else
			if(e[u][v]>w)//去重复边 
			{
    
    
				e[u][v]=w;
				f[wz[u][v]].s=w;
			}
	}
	DIJ(n);
	if(dis[n]==2139062143)
		printf("No answer");
	else
		printf("%d %d",dis[n],ts[n]);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_46975572/article/details/112132130
SSL