hdu 1688 Sightseeing (次短路及次短路数)&&pku3255 Roadblocks &&3191 How Many Paths Are There

hdu1688

题意:找出从S到F两个点之间的最短路和比最短路长1的次短路的条数之和。

分析:最短路很好求,关键是次短路,郁闷呀

不过,如果对最短路的更新距离的过程有更深的认识的话,就好办很多了。

用一个二维数组记录每一个节点距离起始点的最短距离和次短距离,再开一个二维数组记录路径数

更新状态时:

 1)新值小于最短路径长:更新最短路径长,计数;次短路径长,计数

2)新值等于最短路径长:更新最短路径计数

 3)新值大于最短路径长,小于次短路径长:更新次短路径长,计数

4)新值等于次短路径长:更新次短路径计数

View Code
#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;
const int N = 1001;
struct node
{
int v,w;
node(){}
node(int v,int w):v(v),w(w){}
};
vector<node> g[N];
int n,dist[N][2],cnt[N][2];
bool vis[N][2];
void Dijkstra(int s)
{
for(int i=1;i<=n;i++)
{
dist[i][0]=INT_MAX;
dist[i][1]=INT_MAX;
}
memset(vis,false,sizeof(vis));
dist[s][0]=0;
cnt[s][0]=1;
for(int i=0;i<2*n;i++)//每一个节点会被更新俩次,最短和次短,所以是2*n
{
int temp=INT_MAX,u=-1,k;
for(int j=1;j<=n;j++)
if(!vis[j][0] && dist[j][0]<temp)//对于每一个节点,肯定是先更新最短,再更新次短
{
k=0;
temp=dist[j][0];
u=j;
}
else if(!vis[j][1] && dist[j][1]<temp)
{
k=1;
temp=dist[j][1];
u=j;
}
if(u==-1)
break;
vis[u][k]=true;
vector<node>::iterator it=g[u].begin();
for(;it!=g[u].end();it++)
{
int newdis=dist[u][k]+it->w;
int v=it->v;
if(newdis<dist[v][0])
{
dist[v][1]=dist[v][0];
cnt[v][1]=cnt[v][0];
dist[v][0]=newdis;
cnt[v][0]=cnt[u][k];
}
else if(newdis==dist[v][0])
cnt[v][0]+=cnt[u][k];
else if(newdis<dist[v][1])
{
dist[v][1]=newdis;
cnt[v][1]=cnt[u][k];
}
else if(newdis==dist[v][1])
cnt[v][1]+=cnt[u][k];
}
}
}
int main()
{
int T,m,a,b,c;
int s,t;
scanf("%d",&T);
while(T--)
{
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
g[i].clear();
for(int i=0;i<m;i++)
{
scanf("%d %d %d",&a,&b,&c);
g[a].push_back(node(b,c));
}
scanf("%d %d",&s,&t);
Dijkstra(s);
int ans=cnt[t][0];
if(dist[t][1]==dist[t][0]+1)
ans+=cnt[t][1];
printf("%d\n",ans);
}
return 0;
}

以上解释参考该博客http://www.cppblog.com/Davidlrzh/articles/114788.html

pku3255 Roadblocks

题意:求一条次短路,不能等于最短路

可以分别对1和n进行两次Dijkstra,然后枚举边,产生新的一条路,即两点分别到1和n的距离和加上这条边的距离。

当然,也可以用上面类似的方法

方法一
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
const int N = 5001;
struct node
{
int v,w;
node(){}
node(int v,int w):v(v),w(w){}
};
struct edge
{
int u,v,w;
edge(){}
edge(int u,int v,int w):u(u),v(v),w(w){}
}e[100001];
vector<node> g[N];
int n,dists[N],distt[N];
bool vis[N];
void Dijkstra(int dis[],int s)
{
for(int i=1;i<=n;i++)
dis[i]=INT_MAX;
memset(vis,false,sizeof(vis));
dis[s]=0;
for(int i=0;i<n;i++)
{
int temp=INT_MAX,u=-1;
for(int j=1;j<=n;j++)
{
if(!vis[j] &&dis[j]<temp)
{
temp=dis[j];
u=j;
}
}
if(u==-1) break;
vis[u]=true;
vector<node>::iterator it=g[u].begin();
for(;it!=g[u].end();it++)
{
int newdis=dis[u]+it->w;
int v=it->v;
if(newdis<dis[v])
dis[v]=newdis;
}
}
}
int main()
{
int m,a,b,c,minlen;
while(scanf("%d %d",&n,&m)==2)
{
for(int i=1;i<=n;i++)
g[i].clear();
minlen=INT_MAX;
for(int i=0;i<m;i++)
{
scanf("%d %d %d",&a,&b,&c);
g[a].push_back(node(b,c));
g[b].push_back(node(a,c));
e[i]=edge(a,b,c);
minlen=min(c,minlen);
}
Dijkstra(dists,1);
Dijkstra(distt,n);
int mins=dists[n],ans=INT_MAX;
for(int i=0;i<m;i++)
{
int temp=dists[e[i].u]+e[i].w+distt[e[i].v];
if(temp >mins && temp<ans)
ans=temp;
temp=dists[e[i].v]+e[i].w+distt[e[i].u];
if(temp>mins && temp<ans)
ans=temp;
}

printf("%d\n",ans);
}
return 0;
}
方法二 
#include<iostream>
#include<algorithm>
#include<vector>

using namespace std;
const int N = 5001;
struct node
{
int v,w;
node(){}
node(int v,int w):v(v),w(w){}
};
vector<node> g[N];
int n,dist[N][2];
bool vis[N][2];
void Dijkstra(int s)
{
for(int i=1;i<=n;i++)
{
dist[i][0]=INT_MAX;
dist[i][1]=INT_MAX;
}
memset(vis,false,sizeof(vis));
dist[s][0]=0;
for(int i=0;i<2*n;i++)//每一个节点会被更新俩次,最短和次短,所以是2*n
{
int temp=INT_MAX,u=-1,k;
for(int j=1;j<=n;j++)
if(!vis[j][0] && dist[j][0]<temp)//对于每一个节点,肯定是先更新最短,再更新次短
{
k=0;
temp=dist[j][0];
u=j;
}
else if(!vis[j][1] && dist[j][1]<temp)
{
k=1;
temp=dist[j][1];
u=j;
}
if(u==-1)
break;
vis[u][k]=true;
vector<node>::iterator it=g[u].begin();
for(;it!=g[u].end();it++)
{
int newdis=dist[u][k]+it->w;
int v=it->v;
if(newdis<dist[v][0])
{
dist[v][1]=dist[v][0];
dist[v][0]=newdis;
}
else if(newdis<dist[v][1])
dist[v][1]=newdis;
}
}
}
int main()
{
int m,a,b,c;
while(scanf("%d %d",&n,&m)==2)
{
for(int i=1;i<=n;i++)
g[i].clear();
for(int i=0;i<m;i++)
{
scanf("%d %d %d",&a,&b,&c);
g[a].push_back(node(b,c));
g[b].push_back(node(a,c));
}
Dijkstra(1);
printf("%d\n",dist[n][1]);
}
return 0;
}

hdu3191 How Many Paths Are There

几乎一样的题

View Code
#include<iostream>
#include<algorithm>
#include<string>
#include<vector>
using namespace std;
const int N = 55;
struct node
{
int v,w;
node(){}
node(int v,int w):v(v),w(w){}
};
vector<node> g[N];
int n,dist[N][2],cnt[N][2];
bool vis[N][2];
void Dijkstra(int s)
{
for(int i=0;i<n;i++)
{
dist[i][0]=INT_MAX;
dist[i][1]=INT_MAX;
}
memset(vis,false,sizeof(vis));
memset(cnt,0,sizeof(cnt));
dist[s][0]=0;
cnt[s][0]=1;
for(int i=0;i<2*n;i++)
{
int temp=INT_MAX,u=-1,k;
for(int j=0;j<n;j++)
{
if(!vis[j][0] && dist[j][0]<temp)
{
k=0;
u=j;
temp=dist[j][0];
}
else if(!vis[j][1] && dist[j][1]<temp)
{
k=1;
u=j;
temp=dist[j][1];
}
}
if(u==-1) break;
vis[u][k]=true;
vector<node>::iterator it=g[u].begin();
for(;it!=g[u].end();it++)
{
int newdis=dist[u][k]+it->w;
int v=it->v;
if(newdis<dist[v][0])
{
dist[v][1]=dist[v][0];
cnt[v][1]=cnt[v][0];
dist[v][0]=newdis;
cnt[v][0]=cnt[u][k];
}
else if(newdis==dist[v][0])
cnt[v][0]+=cnt[u][k];
else if(newdis<dist[v][1])
{
dist[v][1]=newdis;
cnt[v][1]=cnt[u][k];
}
else if(newdis==dist[v][1])
cnt[v][1]+=cnt[u][k];
}
}
}
int main()
{
int s,t,a,b,c,m;
while(scanf("%d %d %d %d",&n,&m,&s,&t)==4)
{
for(int i=0;i<n;i++)
g[i].clear();
for(int i=0;i<m;i++)
{
scanf("%d %d %d",&a,&b,&c);
g[a].push_back(node(b,c));
}
Dijkstra(s);
printf("%d %d\n",dist[t][1],cnt[t][1]);
}
return 0;
}

 



posted @ 2012-03-23 21:50  枕边梦  阅读(573)  评论(0编辑  收藏  举报