SPFA 跑得快,跑得快。最小花费问题

1443: 最小花费
在n个人中,某些人的银行账号之间可以互相转账。这些人之间转账的手续费各不相同。给定这些人之间转账时需要从转账金额里扣除百分之几的手续费,请问A最少需要多少钱使得转账后B收到100元。

输入

第一行输入两个正整数n,m,分别表示总人数和可以互相转账的人的对数。
以下m行每行输入三个正整数x,y,z,表示标号为x的人和标号为y的人之间互相转账需要扣除z%的手续费 (z<100)。
最后一行输入两个正整数A,B。数据保证A与B之间可以直接或间接地转账

输出

输出A使得B到账100元最少需要的总费用。精确到小数点后8位。

样例输入
3 3
1 2 1
2 3 2
1 3 3
1 3

样例输出
103.07153164

提示

1<=n<=2000

最短路
我给出两种写法,dijstra跑的比较慢,SPFA快了将近一倍。
给出代码

#include
#include
#include
using namespace std;
const int maxn=2505;
int n,m,st,end;
double map[2001][2001];
double d[maxn]={0};
double ans;
bool vis[maxn]={false};
void dijstra(int s)
{
    for(int i=1;i<=n;i++)
    {
        d[i]=map[s][i];
    }
    d[s]=1;
    vis[s]=true;
    for(int i=1;i<=n;i++)
    {
        int u=-1;
        double max=0;
        for(int j=1;j<=n;j++)
        {

            if(vis[j]==false&&d[j]>max)
            {
                max=d[j];
                u=j;
            }
        }
        if(u==-1) return;
        vis[u]=true;
        for(int j=1;j<=n;j++)
        {
            if(!vis[j]&&d[j]map[u][j])
            {
                d[j]=d[u]*map[u][j];
            }
        }
    }
}
int main()
{
  scanf("%d",&n,&m);
  for(int i=1;i<=n;i++)
  {
    int a,b,c;
    scanf("%d%d%d",&a,&b,&c);
    map[a][b]=map[b][a]=double(100-c)/100;
  }
  scanf("%d%d",&st,&end);
  dijstra(st);
  ans=100/d[end];
  printf("%.8f %f",ans,d[end]);
}//用的矩阵存图,算法是djistra; 


下面是SPFA的写法
#include
#include
#include
#include
using namespace std;
int n,m,a,b;
double dis[2010];
double g[2001][2001];
queue<int> q;
int readint()
{
    char ch;int flag=1,num;
    while((ch=getchar())<'0'||ch>'9') if(ch=='-') break;
    if(ch=='-') flag=-1;else num=ch-'0';
    while((ch=getchar())>='0'&&ch<='9') num=num*10+ch-'0';
    return flag*num;
}

struct node{
    int ab;
    int next;
    double hl;
    node ()
    {
        next=-1;
    }
}arc[400000];
int first[20005],cur=0;
void add(const int&a,const int&b,const int&c)
{
    arc[++cur].ab=b;
    arc[cur].next=first[a];
    arc[cur].hl=double (100-c)/100;
    first[a]=cur;
}
void in()
{
    memset(dis,0,sizeof(dis));
    n=readint();
    m=readint();
    int x,y,z;  
    for(int i=1;i<=m;i++)
    {
        x=readint();
        y=readint();
        z=readint();
        add(x,y,z);
        add(y,x,z);
    }
    a=readint();
    b=readint();
}
void SPFA(int x)
{
    bool flag[2010]={0};
    dis[x]=1;
    flag[x]=true;
    q.push(x);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        flag[u]=false;
        m=first[u];
        while(m!=-1)
        {
            int v=arc[m].ab;
            if(dis[v]if(!flag[v])
                {
                    q.push(v);
                    flag[v]=true;
                }
            }   m=arc[m].next;
        }
    }
}
int main()
{
    in();
    SPFA(a);
    printf("%0.8f",100/dis[b]);
    return 0;
}//SPFA的写法,加了读入优化和静态链表的存图方式,速度是香港记者。


你可能感兴趣的:(SPFA 跑得快,跑得快。最小花费问题)