现在的位置: 首页 > 综合 > 正文

poj 3463 Sightseeing

2018年04月23日 ⁄ 综合 ⁄ 共 2520字 ⁄ 字号 评论关闭

题意:旅行团每天固定的从S地出发到达T地,为了省油要求尽量走最短路径或比最短路径长1单位距离的路径,求满足条件的路径条数

这是一次对dijstra的深刻理解 ,好吧......不会做,参考大神思路

因为有重边,所以不能使用邻接矩阵(真的不是因为存不下.....),然后为了减少代码复杂度,使用了链式前向星

struct Edge{
    int v, next, w;
}Graph[maxn*maxn];//跟大神学的,本题采用链式前向星
void add_E(int u, int v, int w){  //A is u ,B is v
    Graph[e_cnt].v=v;
    Graph[e_cnt].next=adj[u];
    Graph[e_cnt].w=w;
    adj[u]=e_cnt++;
}

上面是链式前向星的数据结构,存边,v是一条边的终点,next是上一条邻边,注意是起始点相同;需要一个adj[]数组来保存最后一条和u结点相连的边的编号,这样可以用链来访问所有的边


然后就是二维dijstra ,求出最短路和次短路,最后比较一下次短路是否比最短路多1即可;

#include <set>
#include <map>
#include <ctime>
#include <queue>
#include <cmath>
#include <stack>
#include <limits>
#include <vector>
#include <bitset>
#include <string>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <string.h>
#include <iostream>
#include <algorithm>
#define Si set<int>
#define LL long long
#define pb push_back
#define PS printf(" ")
#define Vi vector<int>
#define LN printf("\n")
#define lson l,m,rt << 1
#define rson m+1,r,rt<<1|1
#define SD(a) scanf("%d",&a)
#define PD(a) printf("%d",a)
#define SET(a,b) memset(a,b,sizeof(a))
#define FF(i,a) for(int i(0);i<(a);i++)
#define FD(i,a) for(int i(a);i>=(1);i--)
#define FOR(i,a,b) for(int i(a);i<=(b);i++)
#define FOD(i,a,b) for(int i(a);i>=(b);i--)
#define readf freopen("input.txt","r",stdin)
#define writef freopen("output.txt","w",stdout)
const int maxn = 1005;
const int INF = 0x3fffffff;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
const double pi = acos(-1.0);
using namespace std;

int N,M;// vertex num , edge num;
bool vis[maxn][2];// visit flag
int e_cnt,adj[maxn],dis[maxn][2],cnt[maxn][2];
struct Edge{
    int v, next, w;
}Graph[maxn*maxn];//跟大神学的,本题采用链式前向星
void add_E(int u, int v, int w){  //A is u ,B is v
    Graph[e_cnt].v=v;
    Graph[e_cnt].next=adj[u];
    Graph[e_cnt].w=w;
    adj[u]=e_cnt++;
}
void dijstra(int S,int F){

    SET(vis,false);
    SET(cnt,0);
    FOR(i,1,N) dis[i][0]=dis[i][1]=INF;
    cnt[S][0]=1;
    dis[S][0]=0;

    int k,tmp,flag;

    FF(i,2*N){
        tmp=INF;
        FOR(j,1,N){
            if(!vis[j][0] && dis[j][0]<tmp){
                tmp=dis[j][0];
                flag=0;
                k=j;
            }else if(!vis[j][1] && dis[j][1]<tmp){
                tmp=dis[j][1];
                flag=1;
                k=j;
            }
        }
        //此时 tmp 是 dis[j][0] 和 dis[j][1] 当中最短的
        if(tmp==INF) break;

        vis[k][flag]=true;
        int w,v;
        for(int j=adj[k];j;j=Graph[j].next){
            w=Graph[j].w;
            v=Graph[j].v;

            if(dis[v][0] > tmp+w ){
                //此时最短路变为次短路
                dis[v][1]=dis[v][0];
                cnt[v][1]=cnt[v][0];
                //新的最短路是tmp+w
                dis[v][0]=tmp+w;
                cnt[v][0]=cnt[k][flag];
            }else if(dis[v][0]== tmp+w){
                cnt[v][0] += cnt[k][flag];
            }else if(dis[v][1] > tmp+w){
                dis[v][1]=tmp+w;
                cnt[v][1]=cnt[k][flag];
            }else if(dis[v][1] == tmp+w){
                cnt[v][1] += cnt[k][flag];
            }
        }
    }
    int ans=cnt[F][0];
    if(dis[F][0]+1==dis[F][1]){
         ans+=cnt[F][1];
    }
    PD(ans);LN;
}
int main()
{
    int cas, S, F;
    SD(cas);
    while(cas--){
        SD(N);SD(M);
        SET(adj,-1);
        e_cnt=1;
        FOR(i,1,M){
            int A,B,L;
            SD(A);SD(B);SD(L);
            add_E(A,B,L);
        }
        SD(S);SD(F);
        dijstra(S,F);
    }
    return 0;
}




抱歉!评论已关闭.