poj 1511(SPFA+邻接表)

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

思路:题目意思很简单就是要求源点到各点的最短路之和,然后再求各点到源点的最短路之和,其实就是建两个图就ok了,其中一个建反图。1000000个点和1000000条边,一开始用SPFA+vector怎么都是TLE,然后换成邻接表就过了=.=。

 1 #include<iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<cmath>

 5 #include<vector>

 6 #include<queue>

 7 using namespace std;

 8 #define MAXN 1000100

 9 #define inf 1LL<<60

10 

11 struct Edge{

12     int v,w,next;

13 }edge1[MAXN*10],edge2[MAXN*10];

14 

15 int head1[MAXN],head2[MAXN];

16 long long dist[MAXN];

17 bool mark[MAXN];

18 int n,m,NE;

19 

20 void Insert(Edge *edge,int *head,int u,int v,int w)

21 {

22     edge[NE].v=v;

23     edge[NE].w=w;

24     edge[NE].next=head[u];

25     head[u]=NE;

26 }

27 

28 

29 long long SPFA(Edge *edge,int *head,int u)

30 {

31     memset(mark,false,(n+2)*sizeof(bool));

32     for(int i=1;i<=n;i++)dist[i]=inf;

33     dist[u]=0;

34     queue<int>Q;

35     Q.push(u);

36     while(!Q.empty()){

37         u=Q.front();

38         Q.pop();

39         mark[u]=false;

40         for(int i=head[u];i!=-1;i=edge[i].next){    

41             int v=edge[i].v,w=edge[i].w;

42             if(dist[u]+w<dist[v]){

43                 dist[v]=dist[u]+w;

44                 if(!mark[v]){ mark[v]=true;Q.push(v); }

45             }

46         }

47     }

48     long long ans=0;

49     for(int i=2;i<=n;i++)ans+=dist[i];

50     return ans;

51 }

52 

53 int main()

54 {

55     int _case,u,v,w;

56     scanf("%d",&_case);

57     while(_case--){

58         scanf("%d%d",&n,&m);

59         NE=0;

60         memset(head1,-1,(n+2)*sizeof(int));

61         memset(head2,-1,(n+2)*sizeof(int));

62         while(m--){

63             scanf("%d%d%d",&u,&v,&w);

64             Insert(edge1,head1,u,v,w);

65             Insert(edge2,head2,v,u,w);//建反图

66             NE++;

67         }

68         printf("%lld\n",SPFA(edge1,head1,1)+SPFA(edge2,head2,1));

69     }

70     return 0;

71 }

72 

73 

74         

75             
View Code

 

你可能感兴趣的:(SPFA)