poj1511:spfa+邻接表(自己模拟)

题目大意:
从1到N分别给出两点之间的有向图,然后让你求,从一到个点的最短路,以及从个点回到1的最短路之和;

思路:
由于边非常多,采用邻接表并且自己模拟(头插入,用VECTER会超时);
刚开始还想着正向从一开始搜,反向从N开始搜,然而错了!!!反向从N开始搜的是从N到个点的最短路,而不是从个点到1的最短路!!!
所以需要建立一个正向图和一个反向图,均从1开始搜就可以得到结果;

#include 
#include 
#include 
#include 
#define inf 0x3f3f3f3f
using namespace std;
const int maxn=1000109;
int n,m,cnt,vis[maxn];
long long ans,d[maxn];
struct node
{
    int v,w,next;
}eadge1[maxn],eadge2[maxn];
int head1[maxn],head2[maxn];
void add(node *eadge,int * head,int u,int v,int w)
{
    eadge[cnt].v=v;
    eadge[cnt].w=w;
    eadge[cnt].next=head[u];
    head[u]=cnt;
}
void spfa(node *eadge,int * head)
{
    memset(vis,0,sizeof vis);
    memset(d,inf,sizeof d);
    queue<int> q;
    q.push(1);
    vis[1]=1,d[1]=0;
    while(!q.empty())
    {

        int u=q.front();
        q.pop();//由于是求所有点的最短路,所以不用加上if(u==n) break;
        vis[u]=0;
        for(int i=head[u];i!=-1;i=eadge[i].next)
        {
         //   cout<<"--i="<
            int v=eadge[i].v,c=eadge[i].w;
            if(d[v]>d[u]+c)
            {
                d[v]=d[u]+c;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=1;
                }
            }
        }
    }
    for(int i=2;i<=n;i++)
        ans+=d[i];
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(head1,-1,sizeof head1);
        memset(head2,-1,sizeof head2);
        cnt=0;
        scanf("%d%d",&n,&m);
        while(m--)
        {
           int u,v,w;
           scanf("%d%d%d",&u,&v,&w);
           add(eadge1,head1,u,v,w);
           add(eadge2,head2,v,u,w);
           cnt++;
        }
        ans=0;
        spfa(eadge1,head1);spfa(eadge2,head2);
        printf("%I64d\n",ans);
    }
    return 0;
}

你可能感兴趣的:(搜索)