//目录

Poj(1511),SPFA

题目链接:http://poj.org/problem?id=1511

嗯,最后一次写SPFA了,以后就套模板了。

题意:给出n个点和n条有向边,求所有点到源点1的来回最短路之和(保证每个点都可以往返源点1).

思路:建反图,从任意一点回来,就变成了反图上的从1到任意一点去。

next记录前驱,head[u],记录u是在第几条边,然后往前扫。例如:edge[0].next = head[1] =0;head[1] = 0;edge[3].next = head[1] =0;head[1] =3;

再扫的时候就是,3->0;

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 1000100
#define inf 1LL<<60

struct Edge
{
    int v,w,next;
} edge1[MAXN*10],edge2[MAXN*10];

int cnt[MAXN];
int head1[MAXN],head2[MAXN];
long long dist[MAXN];
bool mark[MAXN];
int n,m,NE;

void add(Edge *edge,int *head,int u,int v,int w)
{
    edge[NE].v=v;
    edge[NE].w=w;
    edge[NE].next=head[u];  //边的前驱是head[u],之前的那条边
    head[u]=NE;     //head[u] 重新覆盖
}


long long SPFA(Edge *edge,int *head,int u)
{
    memset(mark,false,sizeof(mark));
    memset(cnt,0,sizeof(cnt));
    
    for(int i=1; i<=n; i++)
        dist[i]=inf;
    dist[u]=0;
    mark[u] =true;
    queue<int>Q;
    Q.push(u);
    while(!Q.empty())
    {
        u=Q.front();
        Q.pop();
        mark[u]=false;
        for(int i=head[u]; i!=-1; i=edge[i].next)
        {
            int v=edge[i].v,w=edge[i].w;
            if(dist[u]+w<dist[v])
            {
                dist[v]=dist[u]+w;
                if(!mark[v])
                {
                    mark[v]=true;
                    Q.push(v);
                    
                    /*if(++cnt[v]>n)
                        return false;*/
                }
            }
        }
    }
    long long ans=0;
    for(int i=2; i<=n; i++)ans+=dist[i];
    return ans;
}

int main()
{
    int _case,u,v,w;
    scanf("%d",&_case);
    while(_case--)
    {
        scanf("%d%d",&n,&m);
        NE=0;
        memset(head1,-1,(n+2)*sizeof(int));
        memset(head2,-1,(n+2)*sizeof(int));
        while(m--)
        {
            scanf("%d%d%d",&u,&v,&w);
            add(edge1,head1,u,v,w);
            add(edge2,head2,v,u,w);//建反图
            NE++;
        }
        printf("%lld\n",SPFA(edge1,head1,1)+SPFA(edge2,head2,1));
    }
    return 0;
}

 

posted @ 2016-08-04 21:03  小草的大树梦  阅读(204)  评论(0编辑  收藏  举报