[24 questions sur le flux réseau] Rapport de résolution de problèmes: K. Problème de route aérienne (coût minimum et débit maximum)

Insérez la description de l'image ici
【analyse du problème】

Trouvez les deux chemins disjoints les plus longs et utilisez le coût maximum et le débit maximum pour résoudre.

【Méthode de modélisation】

Divisez la i-ème ville en deux sommets <ia>, <ib>.

1. Pour chaque ville i, connectez (<ia>, <ib>) une arête dirigée d'une capacité de 1 et d'un coût de 1, notamment (<1.a>, <1.b>) et (<Na >, <Nb>) La capacité est réglée sur 2.
2. S'il y a un itinéraire entre les villes i et j (j> i), connectez un tronçon orienté d'une capacité de 1 et d'un coût de 0 de <ib> à <ja>.

Trouvez le coût maximum et le débit maximum de la source <1.a> au puits <Nb>. Si (<1.a>, <1.b>) n'est pas plein, alors il n'y a pas de solution. Sinon, il existe une solution, qui est le coût maximum et le débit maximum-2.

【Analyse de modélisation】

Chaque itinéraire est d'ouest en est. Cette question peut être transformée en trouvant deux chemins disjoints de 1 à N dans le graphe d'itinéraire de sorte que la somme des longueurs de chemin soit la plus grande. Transformer en un modèle de flux réseau consiste à trouver les deux chemins d'augmentation les plus longs. Étant donné que chaque ville ne peut être visitée qu'une seule fois, il est nécessaire de diviser la ville en deux points, de connecter un côté d'une capacité de 1 et de définir le coût sur 1. Étant donné que deux chemins doivent être trouvés, la capacité de bord à l'intérieur du point de départ et du point final doit être définie sur 2. Alors la valeur de flux de coût -2 est la somme des longueurs des deux chemins, pourquoi est-elle réduite de 2, car il y a deux côtés avec une capacité de 2 et le coût de 1 est ajouté. Après avoir trouvé le coût maximum et le débit maximum, si (<1.a>, <1.b>) n'est pas un flux complet, alors nous n'avons pas trouvé assez de chemins pour 2 (peut-être 1 ou 0), donc il n'y a pas de solution.

[Une autre solution au problème]

Le problème de programmation dynamique multi-thread classique.

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<map>
using namespace std;
typedef long long ll;
const int N = 500007, M = 500007, INF = 0x3f3f3f3f;

namespace dinic{
    
    
    const int N = 500007, M = 500007, INF = 0x3f3f3f3f;
    const ll LINF = 0x3f3f3f3f3f;
    int S, T, n;
    int head[N], nex[M], ver[M], tot, cur[N];
    ll dist[N], edge[M], cost[M], maxflow, mincost;
    bool vis[N];

    inline void add(int x, int y, ll z, ll c, bool o = 1){
    
    
        ver[tot] = y;
        edge[tot] = z;
        cost[tot] = c;
        nex[tot] = head[x];
        head[x] = tot ++ ;
        if(o)add(y, x, 0, -c, 0);
    }

    inline bool spfa(){
    
    
        for(int i = 1; i <= n; ++ i)dist[i] =LINF;
        memset(vis, 0, sizeof vis);
        queue<int>q;
        q.push(S);
        dist[S] = 0;
        vis[S] = 1;
        while(q.size()){
    
    
            int x = q.front();
            q.pop();
            vis[x] = 0;
            for(int  i = head[x]; ~i ;i = nex[i]){
    
    
                int y = ver[i];
                ll z = edge[i], c = cost[i];
                if(dist[y] > dist[x] + z && z){
    
    
                    dist[y] = dist[x] + z;
                    if(!vis[y])
                        q.push(y), vis[y] = 1;
                }
            }
        }
        return dist[T] != LINF;
    }
    ll dfs(int x, ll flow = LINF){
    
    
        if(x == T)return flow;
        ll ans = 0, k, i;
        vis[x] = 1;
        for(int i = cur[x]; ~i; i = nex[i]){
    
    
            int y = ver[i];
            ll z = edge[i], c = cost[i];
            if(z && dist[y] == dist[x] + c && vis[y]){
    
    
                k = dfs(y, min(z, flow));
                if(!k)dist[y] = LINF;
                edge[i] -= k;
                edge[i ^ 1] += k;
                ans += k, mincost += k * c, flow -= k;
            }
            vis[x] = 0;
            return ans;
        }
    }

    inline void main(){
    
    
        while(spfa()){
    
    
            for(int i = 1; i <= n; ++ i)
                cur[i] = head[i];
            ll now;
            while((now = dfs(S)))
                maxflow += now;
        }
    }
    inline void init(int _n, int _S, int _T){
    
    
        n = _n, S = _S, T = _T, tot = 0, maxflow = 0, mincost = 0;
        memset(head, -1, sizeof head);
    }
}
map<string, int>ip;
bool way[N];
string s[N], ch;
int n, m, S, T;
int x, y;

inline void dfs1(int x){
    
    
    way[x] = 1;
    cout <<s[x - n] << endl;
    for(int i = dinic::head[x]; ~i; i = dinic::nex[i]){
    
    
        int y = dinic::ver[i], z = dinic::edge[i];
        if(y <= n && z){
    
    
            dfs1(y + n);
            break;
        }
    }
}

inline void dfs2(int x){
    
    
    for(int i = dinic::head[x]; ~i; i = dinic::nex[i]){
    
    
        int y = dinic::ver[i], z = dinic::edge[i];
        if(y <= n && z && !way[y + n])
            dfs2(y + n);

    }
    cout << s[x - n] << endl;
}

int main(){
    
    
    scanf("%d%d", &n, &m);
    S = 1, T = n << 1;
    bool flag = 0;
    dinic::init(n + n + n, S, T);
    for(int i = 1; i <= n; ++ i)
        cin >> s[i], ip[s[i]] = i;
    //i ~ n 表示入点 n + 1 ~ 2 * n 表示出点
    for(int i = 2; i < n; ++ i)
        dinic::add(i, n + i, 1, 1);
        cout << "ok" << endl;
    dinic::add(1, n + 1, 2, 1), dinic::add(n, n + n, 2, 1);
    while(m -- ){
    
    
        cin >> ch, x = ip[ch];
        cin >> ch, y = ip[ch];
        if(x > y)swap(x, y);
        flag |= (x == 1 && y == n);
        dinic::add(x + n, y, 1, 0);
    }
    cout << "ok" << endl;
    dinic:main();
        cout << "ok" << endl;
    if(dinic::maxflow == 2)printf("%d", dinic::mincost - 2);
    else if(dinic::maxflow == 1 && flag){
    
    
        printf("2\n");
        cout << s[1] << endl << s[n] <<endl << s[1] << endl;
        return 0;
    }
    else return !printf("No Solution!\n");
    for(int i = 1;  i <= n + 2; ++ i)
        way[i + n] = 0;
    dfs1(1 + n), dfs2(1 + n);
}

Je suppose que tu aimes

Origine blog.csdn.net/weixin_45697774/article/details/108555522
conseillé
Classement