Pentium.Labs

System全家桶:https://zhuanlan.zhihu.com/c_1238468913098731520

导航

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\n",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\n",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\n",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\n",tx,ty,ans1,ans2);
111         printf("%d\n",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

posted on 2014-10-12 11:13  Pentium.Labs  阅读(260)  评论(0编辑  收藏  举报



Pentium.Lab Since 1998