【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;
}