雕刻时光

just do it……nothing impossible
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

单源起点最短路SPFA——pku3013

Posted on 2011-02-16 16:34  huhuuu  阅读(413)  评论(0编辑  收藏  举报
思路:
可能从题意去解决问题比较棘手,换个角度,实际就是各个(顶点到根节点的最短路*该顶点的权值)的和,类似usaco2.4.4
此题注意点:
1、用int型会超范围,(50000*2^16)>(1<31)
2、用SPFA算法是要注意无向图边的数量是题目所说边的两倍,因为这个看似简单的地方,RE了n久
3、还有就是判断No Answer是只在节点到起点(也就是根节点)没有路时才成立,注意max==0时结果是0,不是No Answer!!!
View Code
#include<iostream>
#include
<queue>
using namespace std;

const __int64 maxn=0xffffffffff;
const __int64 edge_maxn = 100111; //边的最大上限 一定要注意无向图的边是有向图的两倍
const __int64 point_maxn =50111; //点的最大上限
struct node
{
__int64 v;
//终点
__int64 w;//权值
__int64 next;//同一起点的下一条边在edge数组中的位置
}edge[edge_maxn];
__int64 pre[point_maxn];
//以该点为起点的最后一条边存储在edge数组中的位置
__int64 n;//点的数量
__int64 m;//边的数量
queue<__int64>Q;
__int64 dirs[point_maxn];
//起点到i的最短距离
bool vis[point_maxn];//是否存在于队列

__int64 p[point_maxn];
void Init()
{
memset(pre,
-1,sizeof(pre));
__int64 x,y,z;
__int64 index
=1;
__int64 i,j;
for(i=1;i<=m;i++)
{
scanf(
"%I64d%I64d%I64d",&x,&y,&z);
edge[index].v
=y;
edge[index].w
=z;
edge[index].next
=pre[x];
pre[x]
=index++;//保存x起点的最后一条边在edge数组中的位置
swap(x,y);
edge[index].v
=y;
edge[index].w
=z;
edge[index].next
=pre[x];
pre[x]
=index++;
}
}

void SPFA()
{
__int64 start
=1;
while(!Q.empty())
{
Q.pop();
}

memset(vis,
0,sizeof(vis));
fill(dirs,dirs
+point_maxn,maxn);
dirs[start]
=0;
vis[start]
=1;
Q.push(start);
while(!Q.empty())
{
unsigned
int top=Q.front();//边的起点
Q.pop();
vis[top]
=0;
for(int j=pre[top];j!=-1;j=edge[j].next)//pre[x]以该点为起点的最后一条边存储在edge数组中的位置
{
__int64 e
=edge[j].v;//边的终点
if(dirs[e]>edge[j].w+dirs[top])
{
dirs[e]
=edge[j].w+dirs[top];
if(!vis[e])
{
Q.push(e);
vis[e]
=1;
}
}
}
}
}
int main()
{
__int64 t,i;
__int64 max;
scanf(
"%I64d",&t);
while(t--)
{
scanf(
"%I64d%I64d",&n,&m);
for(i=1;i<=n;i++)
{
scanf(
"%I64d",&p[i]);
}
Init();
SPFA();

max
=0;
int rt=0;
for(i=2;i<=n;i++)//要从2开始
{
if(dirs[i]==maxn)
{
printf(
"No Answer\n");
rt
=1;
break;
}
max
+=p[i]*dirs[i];
}
if(rt==0)
{
if(max==0)
{
printf(
"0\n");//注意max==0时结果是0,不是No Answer,错了n久
continue;
}
else
printf(
"%I64d\n",max);
}
}
return 0;
}