• POJ 1511 Invitation Cards【SPFA】



    http://poj.org/problem?id=1511
    POJ 1511 Invitation Cards
    大意:求有向图中从源点到每个节点的往返距离和
    分析:
       1.根据题意建立两幅图,分别对应于正向图和反向图
       2.分别对正向图和反向图求从源点即题中的1结点出发求単源最短路径,
       3. 由2易得,正向图中求得的dis[i]为s到i的最短路,反向图中求得的dis[i]为i到s的最短路
          那么s到i的往返距离即为两个dis相加
       4.在求単源最短路时用SPFA,两次SPFA即可完成

       重点注意:需要读入的数据较大,使用getint()函数可大大减少读数据时间   

    View Code
    1 #include<stdio.h>
    2 #include<string.h>
    3 #include<queue>
    4 #include<iostream>
    5  usingnamespace std;
    6 constint N =1000000+5;//顶点个数
    7 struct EDGE
    8 {
    9 long v;
    10 long price;
    11 EDGE *next;
    12 }edges[2][N],*ind[2][N];//使用指针实现邻接表的存储
    13
    14 __int64 dis[N];
    15 int ednum;//记录边数
    16 bool isInQueue[N];//isInQueue[i]标记i当前是否在队列中
    17 void spfa(int eid,int sid,int n)//spfa求eid图中从sid出发的単源最短路径
    18 {
    19 queue<int>myQueue;
    20 int i,j;
    21 for(i=1;i<=n;i++)
    22 {
    23 dis[i]=-1;
    24 isInQueue[i]=false;
    25 }
    26
    27 int cur;
    28 cur = sid;
    29 dis[cur]=0;
    30 isInQueue[cur]=true;
    31 myQueue.push(cur);
    32
    33 while(!myQueue.empty())
    34 {
    35 cur = myQueue.front();//每次仅对队列中的点进行松弛操作
    36 myQueue.pop();
    37 isInQueue[cur]=false;
    38 for(EDGE *p = ind[eid][cur];p;p=p->next)
    39 {
    40 __int64 temp = p->price+dis[cur];
    41 if(dis[p->v]==-1||temp<dis[p->v])
    42 {
    43 dis[p->v]=temp;
    44 if(isInQueue[p->v]==false)
    45 {
    46 myQueue.push(p->v);
    47 isInQueue[p->v]=true;
    48 }
    49 }
    50 }
    51
    52 }
    53
    54 }
    55
    56 //添加新边
    57 inline void addEdge(long a,long b,long c)
    58 {
    59 EDGE *po,*op;
    60 po =&edges[0][ednum];//正向边
    61 op =&edges[1][ednum];//反向边
    62 ednum++;
    63
    64 po->price = c;
    65 po->v = b;
    66 po->next = ind[0][a];
    67 ind[0][a]=po;
    68
    69 op->price = c;
    70 op->v = a;
    71 op->next = ind[1][b];
    72 ind[1][b]=op;
    73
    74 }
    75
    76 inline long getint() //这个getchar的输入对大数据量输入非常有用,甚至可以挽救效率不高的算法
    77 {
    78 long ret=0;
    79 char tmp;
    80 while(!isdigit(tmp=getchar()));
    81 do{
    82 ret=(ret<<3)+(ret<<1)+tmp-'0';
    83 }while(isdigit(tmp=getchar()));
    84 return ret;
    85 }
    86
    87 int main()
    88 {
    89 int T;
    90 while(scanf("%d",&T)!=EOF)
    91 {
    92 while(T--)
    93 {
    94 int P,Q;
    95 scanf("%d%d",&P,&Q);//P节点个数,Q边个数
    96 for(int i=0;i<=P;i++)
    97 {
    98 ind[0][i]=NULL;
    99 ind[1][i]=NULL;
    100 }
    101
    102 ednum =0;
    103 long a,b,c;
    104 while(Q--)
    105 {
    106 //scanf("%ld%ld%ld",&a,&b,&c);
    107 a = getint();
    108 b = getint();
    109 c = getint();
    110 addEdge(a,b,c);
    111 }
    112 __int64 ans =0;
    113 for(int i=0;i<2;i++)//分别对应于求正向图与反向图的単源最短路
    114 {
    115 spfa(i,1,P);
    116 for(int j=1;j<=P;j++)
    117 ans+=dis[j];
    118 }
    119
    120 printf("%I64d\n",ans);
    121 }
    122 }
    123 return0;
    124 }
  • 相关阅读:
    深入浅出Win32多线程程序设计【2】线程控制
    深入浅出Win32多线程程序设计【1】基本概念
    在两个ASP.NET页面之间传递值
    Javascript基础
    DataGrid的几个小技巧
    推荐取代Visio的中国人的软件——Edraw
    ASP.NET如何防范SQL注入攻击
    软件版本号规定原则
    三层体系结构总结(三)
    .Net工具 .NET文档生成工具2.2
  • 原文地址:https://www.cnblogs.com/AndreMouche/p/2001440.html
Copyright © 2020-2023  润新知