Dijkstra算法

①对跨越两个阵营的边只保留单向边

#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
const int MAXV = 1010;
const int INF = 1e9;

int n, m;//n城市数、m道路数
int camp[MAXV];//记录阵营
int G[MAXV][MAXV];
int d[MAXV];
bool vis[MAXV] = {false};

void init(){
    fill(camp, camp + MAXV, INF);
    fill(G[0], G[0] + MAXV * MAXV, INF);
    fill(d, d + MAXV, INF);
    d[1] = 0;
    fill(vis, vis + MAXV, false);
}

void Dij(){
    for(int i = 0; i < n; i++){
        int u = -1, MIN = INF;
        for(int j = 1; j <= n; j++){
            if(!vis[j] && d[j] < MIN){
                u = j;
                MIN = d[j];
            }
        }
        if(u == -1) return;
        vis[u] = true;
        for(int j = 1; j <= n; j++){
            if(!vis[j] && G[u][j] != INF && d[u] + G[u][j] < d[j]){
                d[j] = d[u] + G[u][j];
            }
        }
    }
}

int main(){
    while(~scanf("%d%d", &n, &m) && n){
        init();
        while(m--){
            int A, B, T;
            scanf("%d %d %d", &A, &B, &T);
            if(G[A][B] > T)
                G[A][B] = G[B][A] = T;
        }
        //输入
        for(int i = 1; i <= n; ++i){
            scanf("%d", &camp[i]);
        }
        for(int i = 1; i <= n; ++i){
            for(int j = 1; j <=n; ++j){
                  //只要把不在一个阵营的边设置成有向边即可:camp1->camp2通,camp2->camp1不通
                if(camp[i] == 2 && camp[j] == 1){
                    G[i][j] = INF;
                }
            }
        }
        Dij();
        d[2] != INF ? printf("%d\n", d[2]) : printf("-1\n"); 
    }
    return 0;
}

②在Dijkstra算法中添加一个限制条件,只能从1阵营到2阵营,不能从2阵营到1阵营

#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
const int MAXV = 1010;
const int INF = 1e9;

int n, m;//n城市数、m道路数
int camp[MAXV];//记录阵营
int G[MAXV][MAXV];
int d[MAXV];
bool vis[MAXV] = {false};

void init(){
    fill(camp, camp + MAXV, INF);
    fill(G[0], G[0] + MAXV * MAXV, INF);
    fill(d, d + MAXV, INF);
    d[1] = 0;
    fill(vis, vis + MAXV, false);
}

void Dij(){
    for(int i = 0; i < n; i++){
        int u = -1, MIN = INF;
        for(int j = 1; j <= n; j++){
            if(!vis[j] && d[j] < MIN){
                u = j;
                MIN = d[j];
            }
        }
        if(u == -1) return;
        vis[u] = true;
        for(int j = 1; j <= n; j++){
            if(!(camp[u] == 2 && camp[j] == 1)){
                if(!vis[j] && G[u][j] != INF && d[u] + G[u][j] < d[j]){
                    d[j] = d[u] + G[u][j];
                }
            }
        }
    }
}

int main(){
    while(~scanf("%d%d", &n, &m) && n){
        init();
        while(m--){
            int A, B, T;//G[A][B]=T
            scanf("%d %d %d", &A, &B, &T);
            if(G[A][B] > T)
                G[A][B] = G[B][A] = T;
        }
        //输入
        for(int i = 1; i <= n; ++i){
            scanf("%d", &camp[i]);
        }

        Dij();
        d[2] != INF ? printf("%d\n", d[2]) : printf("-1\n"); 
    }
    return 0;
}