poj 3463 最短路+次短路

独立写查错不能,就是维护一个次短路的dist

题意:给定一个有向图,问从起点到终点,最短路+比最短路距离长1的路的个数。

Sample Input
2
5 8
1 2 3
1 3 2
1 4 5
2 3 1
2 5 3
3 4 2
3 5 4
4 5 3
1 5
5 6
2 3 1
3 2 1
3 1 10
4 5 2
5 2 7
5 2 7
4 1

Sample Output
3
2

2015-05-14

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<queue>
  7 #include<map>
  8 using namespace std;
  9 #define MOD 1000000007
 10 const int INF=0x3f3f3f3f;
 11 const double eps=1e-5;
 12 typedef long long ll;
 13 #define cl(a) memset(a,0,sizeof(a))
 14 #define ts printf("*****
");
 15 const int MAXN=1005;
 16 int n,m;
 17 #define typec int
 18 int tot,src,des;
 19 int head[MAXN],cnt[MAXN][2],dist[MAXN][2],vis[MAXN][2];//dis[i][0]为最短路,dis[i][1]为次短路
 20 struct Edge
 21 {
 22     int to,next,w;
 23 }edge[MAXN*10];
 24 void addedge(int u,int v,int w)
 25 {
 26     edge[tot].to=v;
 27     edge[tot].w=w;
 28     edge[tot].next=head[u];
 29     head[u]=tot++;
 30 }
 31 void init()
 32 {
 33     memset(head,-1,sizeof(head));
 34     tot=0;
 35 }
 36 int dij()
 37 {
 38     int flag;
 39     memset(dist,0x3f,sizeof(dist));
 40     cl(vis);
 41     cl(cnt);
 42     dist[src][0]=0;
 43     cnt[src][0]=1;
 44     for(int j=1;j<2*n;j++)
 45     {
 46         int u;
 47         int Min=INF;
 48         for(int i=1;i<=n;i++)
 49             if(!vis[i][0]&&dist[i][0]<Min)   //找到比最短路还短的路
 50             {
 51                 u=i;
 52                 flag=0;
 53                 Min=dist[i][0];
 54             }
 55             else if(!vis[i][1]&&dist[i][1]<Min)  //说明比最短路长,比次短路短
 56             {
 57                 u=i;
 58                 flag=1;
 59                 Min=dist[i][1];
 60             }
 61         if(u==-1)break;
 62         vis[u][flag]=true;
 63         for(int i=head[u];i!=-1;i=edge[i].next)
 64         {
 65             int v=edge[i].to;
 66             int w=edge[i].w+Min;
 67             if(dist[v][0]>w) //如果找到的新的值比最短路小,则更新最短路和次短路的值
 68             {
 69                 dist[v][1]=dist[v][0];//更新次短路
 70                 dist[v][0]=w;// 更新最短路
 71                 cnt[v][1]=cnt[v][0];
 72                 cnt[v][0]=cnt[u][flag];//更新最短路和次短路的个数
 73 
 74             }
 75             else if(dist[v][0]==w)   //如果值等于最短路
 76                 cnt[v][0]+=cnt[u][flag];//更新最短路的个数
 77             else if(dist[v][1]>w)    //如果找到的值小于次短路的值,更新次短路
 78             {
 79                 dist[v][1]=w;    //更新次短路的值
 80                 cnt[v][1]=cnt[u][flag];  //更新次短路的个数
 81             }
 82             else if(dist[v][1]==w)   //如果找到的值等于次短路的值
 83                 cnt[v][1]+=cnt[u][flag];//更新次短路的个数
 84         }
 85     }
 86     if(dist[des][0]+1==dist[des][1])//如果次短路的值等于最短路值+1
 87         cnt[des][0]+=cnt[des][1];
 88     return cnt[des][0];
 89 }
 90 int main()
 91 {
 92     int tt,u,v,w;
 93     #ifndef ONLINE_JUDGE
 94     freopen("1.in","r",stdin);
 95     #endif
 96     scanf("%d",&tt);
 97     while(tt--)
 98     {
 99         init();
100         scanf("%d%d",&n,&m);
101         while(m--)
102         {
103             scanf("%d%d%d",&u,&v,&w);
104             addedge(u,v,w);
105         }
106         scanf("%d%d",&src,&des);
107         int ans=dij();
108         printf("%d
",ans);
109     }
110     return 0;
111 }

2015-1-30:

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 #include<queue>
 5 #define VM 1005
 6 #define EM 10010
 7 using namespace std;
 8 const int inf=0x3f3f3f3f;
 9 int head[VM],cnt[VM][2],dist[VM][2],vis[VM][2];//dis[i][0]为最短路,dis[i][1]为次短路
10 int e,src,des,n,m;
11 struct E
12 {
13     int to,w,next;
14 } edge[EM];
15 void add(int cu,int cv,int cw)
16 {
17     edge[e].to=cv;
18     edge[e].w=cw;
19     edge[e].next=head[cu];
20     head[cu]=e ++;
21 }
22 int dij()
23 {
24     int i,j,u,min,flag;
25     memset(dist,0x3f,sizeof(dist));
26     memset(vis,0,sizeof(vis));
27     memset(cnt,0,sizeof(cnt));
28     dist[src][0]=0;
29     cnt[src][0]=1;
30     for(i=1;i<2*n;i++)
31     {
32         min=inf;
33         for(j=1;j<=n;j++)           //找新的最短路和次短路
34             if(!vis[j][0]&&dist[j][0]<min)
35             {
36                 u=j;
37                 flag=0;
38                 min=dist[j][0];
39             }
40             else if(!vis[j][1]&&dist[j][1]<min)
41             {
42                 u=j;
43                 flag=1;
44                 min=dist[j][1];
45             }
46         if(min==inf)
47             break;
48         vis[u][flag]=1;
49         for(j=head[u];j!=-1;j=edge[j].next)
50         {
51             int v=edge[j].to;
52             int w=edge[j].w+min;
53             if(dist[v][0]>w) //如果找到的新的值比最短路小,则更新最短路和次短路的值
54             {
55                 dist[v][1]=dist[v][0];//更新次短路
56                 dist[v][0]=w;// 更新最短路
57                 cnt[v][1]=cnt[v][0];
58                 cnt[v][0]=cnt[u][flag];//更新最短路和次短路的个数
59 
60             }
61             else if(dist[v][0]==w)   //如果值等于最短路
62                 cnt[v][0]+=cnt[u][flag];//更新最短路的个数
63             else if(dist[v][1]>w)    //如果找到的值小于次短路的值,更新次短路
64             {
65                 dist[v][1]=w;    //更新次短路的值
66                 cnt[v][1]=cnt[u][flag];  //更新次短路的个数
67             }
68             else if(dist[v][1]==w)   //如果找到的值等于次短路的值
69                 cnt[v][1]+=cnt[u][flag];//更新次短路的个数
70         }
71 
72     }
73     if(dist[des][0]+1==dist[des][1])//如果次短路的值等于最短路值+1
74         cnt[des][0]+=cnt[des][1];
75     return cnt[des][0];
76 }
77 int main()
78 {
79     int T,u,v,w;
80     scanf("%d",&T);
81     while(T--)
82     {
83         scanf("%d%d",&n,&m);
84         memset(head,0xff,sizeof(head));
85         e=0;
86         while(m--)
87         {
88             scanf("%d%d%d",&u,&v,&w);
89             add(u,v,w);
90         }
91         scanf("%d%d",&src,&des);
92         int ans=dij();
93         printf("%d
",ans);
94     }
95     return 0;
96 }
View Code
原文地址:https://www.cnblogs.com/cnblogs321114287/p/4263009.html