首页 > 代码库 > hdu2680 Choose the best route 最短路(多源转单源)

hdu2680 Choose the best route 最短路(多源转单源)

  此题中起点有1000个,别有20000条。用链式前向星建图,再枚举起点用SPFA的话,超时了。(按理说,两千万的复杂度应该没超吧。不过一般说计算机计算速度 1~10 千万次/秒。也许拿最烂的计算机来卡时间)

  有一个技巧,加一个超级源点。也就是加一个点,使得该点连通所有的起点,并且边的权值为0。这个技巧应用蛮多的。网络流、最小树形图都有题目这样做。

 

#include<iostream>#include<cstdio>#include<cstring>#include<queue>#include<algorithm>using namespace std;const int N = 1010, M=20010;const int INF = 0x3f3f3f3f;struct node{    int to, w, next;};node edge[M];int head[N], dist[N], outq[N];bool vis[N];int tot;bool SPFA(int s, int n ){    int i,k;    for(i=0;i<=n;i++) dist[i]=INF;    memset(vis,0,sizeof(vis));    memset(outq,0,sizeof(outq));    queue<int > q;    while(!q.empty()) q.pop();    vis[s]=1;    dist[s]=0;    q.push(s);    while(!q.empty())    {        int u=q.front();        q.pop();        vis[u]=0;        outq[u]++;        if(outq[u]>n) return 0 ;        k=head[u];        while(k>=0)        {            if(dist[edge[k].to]-edge[k].w>dist[u])            {                dist[edge[k].to]=dist[u]+edge[k].w;                if(!vis[edge[k].to])                {                    vis[edge[k].to]=1;                    q.push(edge[k].to);                }            }            k=edge[k].next;        }    }    return 1;}void addedge(int i,int j,int w){    edge[tot].to=j;    edge[tot].w=w;    edge[tot].next=head[i];    head[i]=tot++;}void init(){    tot=0;    memset(head,-1,sizeof(head));}int main(){    //freopen("test.txt","r",stdin);    int i,j,k,n,m,t,s;    while(scanf("%d%d%d",&n,&m,&t)!=EOF)    {        init();        while(m--)        {            scanf("%d%d%d",&i,&j,&k);            addedge(i,j,k);        }        scanf("%d",&k);        for(i=0;i<k;i++)        {            scanf("%d",&s);            addedge(n+1,s,0);        }        SPFA(n+1,n+1);        if(dist[t]==INF) printf("-1\n");        else printf("%d\n",dist[t]);    }    return 0;}

 

hdu2680 Choose the best route 最短路(多源转单源)