二维最短路

关键词:二维最短路、dij+heap、spfa
题意:已知起点和终点为s和t,还已知一个集合内含有若干三元组(a,b,c).求不能连续经过a->b->c,从s到t的最短路径
解法:设d[u][v]:从s出发,到达“前继是u,当前节点是v”状态的最短路径
然后用spfa或dij+heap优化求解二维最短路径即可
松弛条件:
ma[MP(pre,u)].find(v)==ma[MP(pre,u)].end()&&d[u][v]>d[pre][u]+w

三元组用mapint,int>,set<int> >存储
可以通过前继pre和当前节点u找到下一个v,使得(pre,u,v)在三元组中的节点
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define mem(a,b) memset(a,sizeof(a),b)
#define ll long long
#define INF 0x3f3f3f3f
#define MP make_pair
using namespace std;

const int maxn = 3000+10;
int n,m,k;
vector<int> g[maxn][2];
mapint,int>, set<int> > ma;
int d[maxn][maxn],fa[maxn][maxn];//d[u][v]从起点到达状态“前继是u,当前点是v”的最短路径
bool inq[maxn][maxn];
int cnt[maxn][maxn];
//bool vis[maxn][maxn];
int npre,ans;

void add(int u,int v,int w){
    g[u][0].push_back(v),g[u][1].push_back(w);
}

struct Heapnode{
    int pre,u,d;
    bool operator<(const Heapnode&rhs)const{
        return d>rhs.d;
    }
};


//法一:dij+heap优化
/*void dij(int s,int t){
    priority_queue q;
    memset(vis,0,sizeof(vis));
    memset(fa,-1,sizeof(fa));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            d[i][j]=INF;
    d[0][1]=0;
    q.push((Heapnode){0,1,d[0][1]});
    while(!q.empty()){
        Heapnode x=q.top();q.pop();
        int pre=x.pre,u=x.u;
        if(vis[pre][u]) continue;
        vis[pre][u]=1;
        for(int i=0;id[pre][u]+w){
                d[u][v]=d[pre][u]+w;
                fa[u][v]=pre;
                q.push((Heapnode){u,v,d[u][v]});
            }
        }
    }
}*/

//法二:spfa
void spfa(int s,int t){
    queue q;
    memset(inq,0,sizeof(inq));
    memset(cnt,0,sizeof(cnt));
    memset(fa,-1,sizeof(fa));
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)
            d[i][j]=INF;
    d[0][1]=0,inq[0][1]=1;
    q.push((Heapnode){0,1,d[0][1]});
    while(!q.empty()){
        Heapnode x=q.front();q.pop();
        int pre=x.pre,u=x.u;
        inq[pre][u]=0;
        for(int i=0;i0].size();i++){
            int v=g[u][0][i],w=g[u][1][i];
            if(ma[MP(pre,u)].find(v)==ma[MP(pre,u)].end()&&d[u][v]>d[pre][u]+w){
                d[u][v]=d[pre][u]+w;

                fa[u][v]=pre;
                q.push((Heapnode){u,v,d[u][v]});
                inq[u][v]=1;
                if(++cnt[u][v]>n) return ;
            }
        }
    }
}

void print(int pre,int u){
    if(u==1) { printf("%d",u); return; }
    print(fa[pre][u],pre);
    printf(" %d",u);
}

int main(){
    //freopen("a.txt","r",stdin);
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++) { g[i][0].clear(); g[i][1].clear(); }
    for(int i=1;i<=m;i++){
        int a,b,c;
        scanf("%d%d",&a,&b);
        add(a,b,1),add(b,a,1);
    }
    ma.clear();
    for(int i=1;i<=k;i++){
        int a,b,c;
        scanf("%d%d%d",&a,&b,&c);
        ma[MP(a,b)].insert(c);
    }
    //dij(1,n);法一
    spfa(1,n);//法二
    npre=-1,ans=INF;
    for(int i=1;iif(d[i][n]if(ans!=INF){
        printf("%d\n",ans);
        print(npre,n);
        printf("\n");
    }
    else printf("-1\n");
}

你可能感兴趣的:(acm_图论)