zoukankan      html  css  js  c++  java
  • poj 3463 最短路与次短路&&统计个数

    题意:求最短路和比最短路长度多1的次短路的个数

    本来想图(有)方(模)便(版)用spfa的,结果妹纸要我看看dijkstra怎么解....

    写了三遍orz

    Ver1.0:堆优化+邻接表,WA

      1 //不能用堆优化+邻接表,因为需要处理dis[i][0]和dis[i][1]两套,如果都挤到一个堆里就乱套了
      2 
      3 #include <iostream>
      4 #include <cstdio>
      5 #include <queue>
      6 #include <cstring>
      7 #include <vector>
      8 using namespace std;
      9 const int Ni = 10000;
     10 const int INF = 1<<27;
     11 struct node
     12 {                   //eg[i].x  eg[i].d    i:start  x:end   d:distance
     13     int x,d;
     14     node(){}
     15     node(int a,int b){x=a;d=b;}
     16     bool operator < (const node & a) const      //用于优先队列, 取距离原点最近的点
     17     {
     18         if(d==a.d) return x<a.x;
     19         else return d > a.d;
     20     }
     21 };
     22 vector<node> eg[Ni];
     23 int dis[Ni][5],cnt[Ni][5],n,T;
     24 
     25 void Dijkstra(int s)    //1.比最短路短2.等于最短路3.长于最短路但短于次短路4.等于次短路
     26 {
     27     memset(dis,0,sizeof(dis));
     28     memset(cnt,0,sizeof(cnt));
     29 
     30     int i;
     31     for(i=0;i<=n;i++)
     32     {
     33         dis[i][1]=INF;
     34         dis[i][2]=INF;
     35     }
     36     dis[s][1]=0;
     37     dis[s][2]=0;
     38     priority_queue<node> q;         //q:优先队列,用来取离原点最近的顶点
     39     q.push(node(s,dis[s][1]));      //初始只有一个原点自己
     40     while(!q.empty())
     41     {
     42         node x=q.top();q.pop();
     43         for(i=0;i<eg[x.x].size();i++)
     44         {
     45             node y=eg[x.x][i];
     46             if(dis[y.x][1]>x.d+y.d)       //1
     47             {
     48                 cnt[y.x][1]=1;
     49                 cnt[y.x][2]=1;
     50                 dis[y.x][2]=dis[y.x][1];
     51                 dis[y.x][1]=x.d+y.d;
     52                 q.push(node(y.x,dis[y.x][1]));
     53             }
     54             else if (dis[y.x][1]==x.d+y.d)      //2
     55             {
     56                 cnt[y.x][1]++;
     57             }
     58             else if ((dis[y.x][1]<x.d+y.d)&&(x.d+y.d<dis[y.x][2]))      //3
     59             {
     60                 cnt[y.x][2]=1;
     61                 dis[y.x][2]=x.d+y.d;
     62             }
     63             else if (x.d+y.d==dis[y.x][2])      //4
     64             {
     65                 cnt[y.x][2]++;
     66             }
     67         }
     68     }
     69 }
     70 
     71 void debug()
     72 {
     73     cout<<"Debug only"<<endl;
     74     for (int i=1;i<=n;i++)
     75         printf("%d - %d %d - %d %d
    ",i,dis[i][1],cnt[i][1],dis[i][2],cnt[i][2]);
     76     cout<<ans1<<"    "<<ans2<<endl;
     77     
     78 }
     79 
     80 int main()
     81 {
     82     scanf("%d",&T);
     83     while (T--)
     84     {
     85         int a,b,d,m,k,st;
     86         scanf("%d%d",&n,&m);
     87         for(int i=0;i<=n;i++) eg[i].clear();
     88         while(m--)
     89         {
     90             scanf("%d%d%d",&a,&b,&d);
     91             eg[a].push_back(node(b,d));
     92         }
     93         scanf("%d %d",&k,&st);
     94         Dijkstra(k);
     95 
     96         debug1();
     97         
     98         int t1=dis[st][1],t2=dis[st][2],ans1=cnt[st][1],ans2;
     99         if (t2-t1==1)
    100             ans2=cnt[st][2];
    101         else ans2=0;
    102         printf("%d
    ",ans1+ans2);
    103     }
    104 
    105     return 0;
    106 }
    View Code

    Ver2.0:邻接矩阵,WA

     1 //不能用邻接矩阵,因为会有重边
     2 
     3 #include <iostream>
     4 #include <cstring>
     5 using namespace std;
     6 #define MAXINT 9999999
     7 
     8 int minx,minj,x,y,t,k,n,m,tmp,st,flag;
     9 int v[1010][3],d[1010][3],cnt[1010][3],a[1010][1010];
    10 
    11 int main()
    12 {
    13     int T;
    14     cin>>T;
    15     while (T--)
    16     {
    17         cin>>n>>m;
    18         memset(a,0,sizeof(a));
    19         memset(d,MAXINT,sizeof(d));
    20         memset(v,0,sizeof(v));
    21         memset(cnt,0,sizeof(cnt));
    22 
    23         for (int i=1;i<=m;i++)
    24         {
    25             cin>>x>>y>>t;
    26             a[x][y]=t;
    27         }
    28         cin>>k>>st;
    29         d[k][1]=0;  //d[k][2]=0;
    30         cnt[k][1]=1;   // cnt[k][2]=1;
    31 
    32         for (int i=1;i<=2*n;i++)
    33         {
    34             minx=MAXINT;
    35             for (int j=1;j<=n;j++)
    36             {
    37                 if ((v[j][1]==0)&&(d[j][1]<minx))
    38                 {
    39                     minx=d[j][1];
    40                     minj=j;
    41                     flag=1;
    42                 }
    43                 if ((v[j][2]==0)&&(d[j][2]<minx))
    44                 {
    45                     minx=d[j][2];
    46                     minj=j;
    47                     flag=2;
    48                 }
    49             }
    50             v[minj][flag]=1;
    51             for (int j=1;j<=n;j++)
    52                // if ((v[j][1]==0)&&(a[minj][j]>0))
    53                if (a[minj][j]>0)
    54             {
    55                 tmp=minx+a[minj][j];
    56 
    57                 if (tmp<d[j][1])
    58                 {
    59                     d[j][2]=d[j][1];
    60                     d[j][1]=tmp;
    61                     cnt[j][2]=cnt[j][1];
    62                     cnt[j][1]=cnt[minj][flag];
    63                 }
    64                 else if (tmp==d[j][1])
    65                 {
    66                     cnt[j][1]+=cnt[minj][flag];
    67                 }
    68                 else if (tmp<d[j][2])
    69                 {
    70                     d[j][2]=tmp;
    71                     cnt[j][2]=cnt[minj][flag];
    72                 }
    73                 else if (tmp==d[j][2])
    74                 {
    75                     cnt[j][2]+=cnt[minj][flag];
    76                 }
    77             }
    78     }
    79 
    80     for (int i=1;i<=n;i++)
    81         cout<<d[i][1]<<" "<<cnt[i][1]<<" = "<<d[i][2]<<" "<<cnt[i][2]<<endl;
    82     cout<<endl;
    83     int t1=d[st][1],t2=d[st][2],ans1=cnt[st][1],ans2;
    84     if (t2==t1+1) ans2=cnt[st][2]; else ans2=0;
    85     cout<<ans1+ans2<<endl;
    86     }
    87     return 0;
    88 }
    View Code

    Ver3.0:朴素n^2算法+邻接表  AC

      1 #include <stdio.h>
      2 #include <string.h>
      3 #define INF 999999
      4 
      5 struct node
      6 {
      7     int to,dat;
      8 }edge[1010][1010];
      9 
     10 int cnt[1010][2],d[1010][2],vis[1010][2];
     11 int x,y,z,n,m,T,st,ed;
     12 
     13 void insert_node(int x,int y,int z)
     14 {
     15     edge[x][0].dat++;
     16     int tmp=edge[x][0].dat;
     17     edge[x][tmp].to=y;
     18     edge[x][tmp].dat=z;
     19 }
     20 
     21 void dijkstra()
     22 {
     23     memset(vis,0,sizeof(vis));
     24     memset(d,INF,sizeof(d));
     25     memset(cnt,0,sizeof(cnt));
     26     d[st][0]=0;
     27     cnt[st][0]=1;
     28 
     29     for (int i=1;i<=2*n;i++)
     30     {
     31         int minj,flag,minx=INF;
     32         for (int j=1;j<=n;j++)
     33             if ((vis[j][0]==0)&&(d[j][0]<minx))
     34             {
     35                 minx=d[j][0];
     36                 minj=j;
     37                 flag=0;
     38             }
     39             else if ((vis[j][1]==0)&&(d[j][1]<minx))
     40             {
     41                 minx=d[j][1];
     42                 minj=j;
     43                 flag=1;
     44             }
     45         vis[minj][flag]=1;
     46         int tmp=edge[minj][0].dat;
     47         for (int j=1;j<=tmp;j++)
     48         {
     49             int yy=edge[minj][j].to;
     50             int zz=edge[minj][j].dat;
     51             //if (vis[yy][flag]==0)
     52             //{
     53                 int tm=minx+zz;
     54                 if (tm<d[yy][0])
     55                 {
     56                     d[yy][1]=d[yy][0];
     57                     cnt[yy][1]=cnt[yy][0];
     58                     d[yy][0]=tm;
     59                     cnt[yy][0]=cnt[minj][flag];
     60                 }
     61                 else if (tm==d[yy][0])
     62                 {
     63                     cnt[yy][0]+=cnt[minj][flag];
     64                 }
     65                 else if (tm<d[yy][1])
     66                 {
     67                     d[yy][1]=tm;
     68                     cnt[yy][1]=cnt[minj][flag];
     69                 }
     70                 else if (tm==d[yy][1])
     71                 {
     72                     cnt[yy][1]+=cnt[minj][flag];
     73                 }
     74             //}
     75 
     76         }
     77 
     78     }
     79 }
     80 
     81 int main()
     82 {
     83 //    freopen("in.txt","r",stdin);
     84 
     85     scanf("%d",&T);
     86     while (T--)
     87     {
     88         memset(edge,0,sizeof(edge));
     89         scanf("%d %d",&n,&m);
     90         for (int i=1;i<=m;i++)
     91         {
     92             scanf("%d %d %d",&x,&y,&z);
     93             insert_node(x,y,z);
     94         }
     95         scanf("%d %d",&st,&ed);
     96 
     97 /*
     98         for (int i=1;i<=n;i++)
     99             for (int j=1;j<=edge[i][0].dat;j++)
    100                 printf("Debug: %d -> %d = %d
    ",i,edge[i][j].to,edge[i][j].dat);
    101 */
    102 
    103         dijkstra();
    104 
    105         int tx,ty,ans2,ans1;
    106         tx=d[ed][0];    ty=d[ed][1];
    107         ans1=cnt[ed][0];
    108         if (ty-tx==1)   ans2=cnt[ed][1];
    109             else ans2=0;
    110 //        printf("%Debug: %d %d %d %d
    ",tx,ty,ans1,ans2);
    111         printf("%d
    ",ans1+ans2);
    112     }
    113     return 0;
    114 }
    View Code

    邻接表很少用到都不大会写了>_<

    dij松弛的条件改变下,有四种情况
    1.比最短路短2.等于最短路3.长与最短路但短于次短路4.等于次短路

    d[i][0]记最短路, d[i][1]记次短路

    注意这里:

    int tm=minx+zz;
    if (tm<d[yy][0])
    {
        d[yy][1]=d[yy][0];
        cnt[yy][1]=cnt[yy][0];
        d[yy][0]=tm;
        cnt[yy][0]=cnt[minj][flag];        
    }
    else if (tm==d[yy][0])
    {
        cnt[yy][0]+=cnt[minj][flag];
        
        //因为松弛操作是从minj点开始的
        //(d[minj]+a[minj,j]<d[j])
        //所以记录cnt的时候要+=cnt[minj][flag]
        //一开始以为直接+1就行,WA了
        //前面的cnt[yy][0]=cnt[minj][flag]同理
    }
    else if (tm<d[yy][1])
    {
        d[yy][1]=tm;
        cnt[yy][1]=cnt[minj][flag];
    }
    else if (tm==d[yy][1])
    {
        cnt[yy][1]+=cnt[minj][flag];
    }

    Reference:

    http://blog.csdn.net/wmn_wmn/article/details/7376707

    http://www.cnblogs.com/Missa/archive/2012/08/31/2665244.html

  • 相关阅读:
    直线方程和直线系方程
    多个参数之和积的取值范围
    解析几何习题
    React之Perf
    一文看懂npm、yarn、pnpm之间的区别
    Cannot read property 'properties' of undefined
    为什么要用PolyFill(JS中的修补匠)
    es6-promise
    原生js实现each方法
    有趣的js获取input标签中光标的索引
  • 原文地址:https://www.cnblogs.com/pdev/p/4020289.html
Copyright © 2011-2022 走看看