题目:
SightseeingProblem Description Tour operator Your Personal Holiday organises guided bus trips across the Benelux. Every day the bus moves from one city S to another city F. On this way, the tourists in the bus can see the sights alongside the route travelled. Moreover, the bus makes a number of stops (zero or more) at some beautiful cities, where the tourists get out to see the local sights. Input The first line of the input file contains a single number: the number of test cases to follow. Each test case has the following format: Output For every test case in the input file, the output should contain a single number, on a single line: the number of routes of minimal length or one distance unit longer. Test cases are such, that this number is at most 10^9 = 1,000,000,000. 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
|
题意:找最短路与次短路,并且次短路=最短路+1,求满足该条件的次短路条数+最短路条数
题意分析:裸的最短路与次短路问题
重要的是我通过这个题目知道了最短路次短路求法 和 求最短路次短路条数的方法,而且之前不停的SPFA+DFS或者是Dij+DFS,加深了对DFS的理解,两点之间有不同路,并且两条路都得遍历SPFA,Dij都不能用,只能用DFS标记点,然后回溯,或者是使用这个题目的方法,类似于DP的思想对点的方案数用num进行记录
AC代码:
#include<bits/stdc++.h>
#define N 1005
#define M 10005
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
int t,c,S,F,n,m;
int head[N],dis[N][2],num[N][2];//0表示最短路,1表示次短路,分别表示最短路次短路的距离,最短路次短路有多少条
bool vis[N][2];//0表示最短路是否走过,1表示次短路是否走过
struct ljh
{
int to,next,w;
}e[M];
struct xqy
{
int x,d,id;
xqy(int x=0,int d=0,int id=0):x(x),d(d),id(id){}
bool operator < (const xqy&a)const
{
return a.d<d;
}
};
inline void add(int x,int y,int z)
{
e[c].next=head[x];
e[c].to=y;
e[c].w=z;
head[x]=c++;
}
void Dij(int s)
{
for(int i=1;i<=n;i++)dis[i][0]=dis[i][1]=INF;
memset(vis,0,sizeof(vis));
memset(num,0,sizeof(num));
dis[s][0]=0;
num[s][0]=1;
priority_queue<xqy>q;
q.push(xqy(s,0,0));
while(!q.empty())
{
xqy now=q.top();
q.pop();
int x=now.x;
int id=now.id;
if(vis[x][id])continue;
vis[x][id]=1;
for(int i=head[x];i!=-1;i=e[i].next)
{
int nex=e[i].to;
int temp=now.d+e[i].w;
// cout<<temp<<endl;
if(dis[nex][0]>temp)//比较最短路,比最短路小
{
dis[nex][1]=dis[nex][0];
num[nex][1]=num[nex][0];
q.push(xqy(nex,dis[nex][1],1));
dis[nex][0]=temp;
num[nex][0]=num[x][0];
q.push(xqy(nex,dis[nex][0],0));
}
else if(dis[nex][0]==temp)//等于最短路
{
num[nex][0]+=num[x][0];//相同的一条路,只会由最短路走过来
}
else if(dis[nex][1]>temp)//比次短路小
{
dis[nex][1]=temp;
num[nex][1]=num[x][id];//因为他也可能是由之前的最短路走出来的次短路
q.push(xqy(nex,dis[nex][1],1));
}
else if(dis[nex][1]==temp)
{
num[nex][1]+=num[x][id];
}
}
}
}
int main()
{
scanf("%d",&t);
while(t--)
{
c=0;
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
scanf("%d%d",&S,&F);
Dij(S);
// cout<<dis[F][0]<<" "<<dis[F][1]<<endl;
if(dis[F][0]+1==dis[F][1])printf("%d\n",num[F][0]+num[F][1]);
else printf("%d\n",num[F][0]);
}
return 0;
}
SPFA+DFS代码:(T了,只是记录学习一下)
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define M 10005
#define N 1005
using namespace std;
int t,n,m,S,F,ans,diss,c;
int dis[N],head[N];
bool vis[N];
struct ljh
{
int next,to,w;
}e[M];
inline void add(int x,int y,int z)
{
e[c].next=head[x];
e[c].w=z;
e[c].to=y;
head[x]=c++;
}
void SPFA1(int x)
{
for(int i=1;i<=n;i++)dis[i]=INF;
memset(vis,0,sizeof(vis));
queue<int>q;
dis[x]=0;
vis[x]=1;
q.push(x);
while(!q.empty())
{
int now=q.front();
q.pop();
vis[now]=0;
for(int i=head[now];i!=-1;i=e[i].next)
{
int nex=e[i].to;
if(dis[nex]>dis[now]+e[i].w)
{
dis[nex]=dis[now]+e[i].w;
if(!vis[nex])
{
q.push(nex);
vis[nex]=1;
}
}
}
}
return ;
}
void dfs(int x,int fa,int k)
{
// cout<<x<<" "<<fa<<" "<<k<<endl;
if(x==F)
{
if(k==diss||k==diss+1)ans++;
return;
}
vis[x]=1;
for(int i=head[x];i!=-1;i=e[i].next)
{
int nex=e[i].to;
if(nex==fa)continue;
if(!vis[nex])dfs(nex,x,k+e[i].w);
// k-=e[i].w;
}
vis[x]=0;
}
int main()
{
scanf("%d",&t);
while(t--)
{
c=0;
ans=0;
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
scanf("%d%d",&S,&F);
SPFA1(S);
diss=dis[F];
// cout<<diss<<endl;
dfs(S,-1,0);
printf("%d\n",ans);
}
return 0;
}
Dij+DFS代码:(也是T,可以不看)
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define M 10005
#define N 1005
using namespace std;
int t,n,m,S,F,ans,diss,c;
int dis[N],head[N];
bool vis[N];
struct ljh
{
int next,to,w;
}e[M];
struct xqy
{
int x,d;
xqy(int x=0,int d=0):x(x),d(d){};
bool operator < (const xqy&a)const{
return a.d<d;
}
};
inline void add(int x,int y,int z)
{
e[c].next=head[x];
e[c].w=z;
e[c].to=y;
head[x]=c++;
}
void Dij(int s)
{
priority_queue<xqy>q;
memset(vis,0,sizeof(vis));
for(int i=1;i<=N;i++)dis[i]=INF;
dis[s]=0;
q.push(xqy(s,0));
while(!q.empty())
{
xqy now=q.top();
q.pop();
int x=now.x;
if(vis[x])continue;
vis[x]=1;
for(int i=head[x];i!=-1;i=e[i].next)
{
int nex=e[i].to;
if(dis[nex]>dis[x]+e[i].w)
{
dis[nex]=dis[x]+e[i].w;
q.push(xqy(nex,dis[nex]));
}
}
}
}
void dfs(int x,int fa,int k)
{
// cout<<x<<" "<<fa<<" "<<k<<endl;
if(x==F)
{
if(k==diss||k==diss+1)ans++;
return;
}
vis[x]=1;
for(int i=head[x];i!=-1;i=e[i].next)
{
int nex=e[i].to;
if(nex==fa)continue;
if(!vis[nex])dfs(nex,x,k+e[i].w);
// k-=e[i].w;
}
vis[x]=0;
}
int main()
{
scanf("%d",&t);
while(t--)
{
c=0;
ans=0;
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
scanf("%d%d",&S,&F);
Dij(S);
diss=dis[F];
// cout<<diss<<endl;
memset(vis,0,sizeof(vis));
dfs(S,-1,0);
printf("%d\n",ans);
}
return 0;
}
后来想纯DFS,但是题目给的答案有1e9所以最后MLE了,代码:
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define M 10005
#define N 1005
#define LL long long
using namespace std;
int t,n,m,S,F,ans,diss,c,num;
int dis[N],head[N];
bool vis[N];
map<LL,LL>s;
struct ljh
{
int next,to,w;
}e[M];
inline void add(int x,int y,int z)
{
e[c].next=head[x];
e[c].w=z;
e[c].to=y;
head[x]=c++;
}
void dfs(int x,int fa,int k)
{
// cout<<x<<" "<<fa<<" "<<k<<endl;
if(x==F)
{
q.push(k);
// num++;
// s[num]=k;
// if(k==diss||k==diss+1)ans++;
return;
}
vis[x]=1;
for(int i=head[x];i!=-1;i=e[i].next)
{
int nex=e[i].to;
if(nex==fa)continue;
if(!vis[nex])dfs(nex,x,k+e[i].w);
// k-=e[i].w;
}
vis[x]=0;
}
int main()
{
scanf("%d",&t);
while(t--)
{
num=0;
c=0;
ans=0;
memset(head,-1,sizeof(head));
while(!q.empty())q.pop();
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
scanf("%d%d",&S,&F);
// SPFA(S);
dfs(S,-1,0);
int diss=q.top();
while(!q.empty())
{
if(q.top()==diss||q.top()==diss+1){ans++;
q.pop();}
else break;
}
// for(LL i=1;i<=k;i++)if(s[i]==dis[F]||s[i]==dis[F]+1)ans++;
printf("%d\n",ans);
}
return 0;
}