[东莞市选2007]最难的问题_纪中1001_spfa

99 篇文章 0 订阅
56 篇文章 0 订阅

Description

  这是一个很难的问题,你要找出“12345678987654321!”答案里一共含有多少个“0”,“!”表示阶乘的意思。   其实,我是在开玩笑的,地球上没有人真正能成功的解决这个问题。   实际上,我是一个间谍,我从敌人手中偷取了一些很重要的秘密,我只想以尽量少的时间离开敌人的基地。 敌人的基地地图可以用一张网络图表示,交叉路口可表示为结点,通路可表示为边,我需要从基地总部逃出到撤离点。到底怎样走才最快呢?幸好我有一台超强的掌上电脑,请尽快帮我解决这个问题!

Input

  数据第一行是两个整数N和M,(1<=N<=200,0<=M<=10000),分别表示交叉路口数量与通路数量。接下来M行每行有三个整数i,j,k(i!=j,1<=k<=10000),表示有一条长度为k的无向通路连接路口i与路口j。注意路口i与路口j间可能有多条不同长度的通路。你可以假定交叉路口是用1到n的整数来标识的,编号1是基地总部,编号n是撤离

Output

  输出只有一个整数,为最短的逃离距离,如果不可能逃出,则输出“-1”。

Sample Input

2 1 1 2 3

Sample Output

3

思路

一直没有刷到的题,完成了多年夙愿!!!!!!!!!!

spfa最短路,模版啊模版

值得注意的是给定图为无向图,连点要连双向

注意要判断是否为-1

#include <stdio.h>
#include <queue>
using namespace std;
struct edge
{
    int x,y,w,next;
};
queue<int>state;
edge e[40001];
bool v[201];
int ls[201],dis[201];
int n,m,p=1,maxE=0;
int inf=0xffffff;
void add(int x,int y,int w)
{
    e[++maxE]=(edge){x,y,w,ls[x]};
    ls[x]=maxE;
}
void spfa(void)
{
    for (int i=1;i<=n;i++)
        dis[i]=inf;
    state.push(p);
    v[p]=true;
    dis[p]=0;
    while (state.size())
    {
        for (int t=ls[state.front()];t;t=e[t].next)
        if (dis[e[t].x]+e[t].w<dis[e[t].y])
        {
            dis[e[t].y]=dis[e[t].x]+e[t].w;
            if (!v[e[t].y])
            {
                v[e[t].y]=true;
                state.push(e[t].y);
            }
        }
        v[state.back()]=false;
        state.pop();
    }
    if (dis[n]==inf)
        dis[n]=-1;
    printf("%d\n",dis[n]);
}
void init(void)
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=m;i++)
    {
        int x,y,w;
        scanf("%d%d%d",&x,&y,&w);
        add(x,y,w);
        add(y,x,w);
    }
}
int main()
{
    init();
    spfa();
    return 0;
}
type
  rec=record
    x,y,w,next:int64;
  end;
const
  p=1;
var
  n,m,maxE:longint;
  g:array[1..20000]of rec;
  ls,d:array[1..1000]of int64;
  state:array[1..1000]of longint;
  v:array[1..1000]of boolean;
procedure add(x,y,w:Longint);
begin
  inc(maxE);
  g[maxE].x:=x;
  g[maxE].y:=y;
  g[maxE].w:=w;
  g[maxE].next:=ls[x];
  ls[x]:=maxE;
  inc(maxE);
  g[maxE].x:=y;
  g[maxE].y:=x;
  g[maxE].w:=w;
  g[maxE].next:=ls[y];
  ls[y]:=maxE;
end;
procedure init;
var
  i,x,y,w:longint;
begin
  readln(n,m);
  fillchar(ls,sizeof(ls),0);
  maxE:=0;
  for i:=1 to m do
  begin
    readln(x,y,w);
    add(x,y,w);
  end;
end;
procedure spfa;
var
  head,tail,t:longint;
  inf:int64;
begin
  head:=0;
  tail:=1;
  fillchar(state,sizeof(state),0);
  fillchar(v,sizeof(v),false);
  fillchar(d,sizeof(d),$7f);
  inf:=d[1];
  d[p]:=0;
  state[1]:=p;
  v[p]:=true;
  repeat
    inc(head);
    t:=ls[state[head]];
    while t>0 do
    with g[t] do
    begin
      if d[x]+w<d[y] then
      begin
        d[y]:=d[x]+w;
        if not v[y] then
        begin
          v[y]:=true;
          inc(tail);
          state[tail]:=y;
        end;
      end;
      t:=next;
    end;
    v[state[head]]:=false;
  until head>=tail;
  if d[n]=inf then
  d[n]:=-1;
  writeln(d[n]);
end;
begin
  init;
  spfa;
end.
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值