[24 preguntas sobre el flujo de la red] Informe de resolución de problemas: K. Problema de ruta aérea (costo mínimo y flujo máximo)

Inserte la descripción de la imagen aquí
【análisis del problema】

Encuentre los dos caminos disjuntos más largos y use el costo máximo y el flujo máximo para resolver.

【Método de modelado】

Divida la i-ésima ciudad en dos vértices <ia>, <ib>.

1. Para cada ciudad i, conecte (<ia>, <ib>) un borde dirigido con una capacidad de 1 y un costo de 1, especialmente (<1.a>, <1.b>) y (<Na >, <Nb>) La capacidad se establece en 2.
2. Si hay una ruta entre las ciudades i y j (j> i), conecte un borde dirigido con una capacidad de 1 y un costo de 0 de <ib> a <ja>.

Encuentre el costo máximo y el flujo máximo desde la fuente <1.a> hasta el sumidero <Nb>. Si (<1.a>, <1.b>) no está lleno, entonces no hay solución. De lo contrario, hay una solución, que es el costo máximo y el flujo máximo-2.

【Análisis de modelado】

Cada ruta es de oeste a este. Esta pregunta se puede transformar en encontrar dos caminos separados de 1 a N en el gráfico de ruta, de modo que la suma de las longitudes de los caminos sea la mayor. Transformarse en un modelo de flujo de red es encontrar las dos rutas de aumento más largas. Dado que cada ciudad solo se puede visitar una vez, es necesario dividir la ciudad en dos puntos, conectar un lado con una capacidad de 1 y establecer el costo en 1. Debido a que se deben encontrar dos rutas, la capacidad del borde dentro del punto de inicio y el punto final debe establecerse en 2. Entonces el valor de flujo de costo -2 es la suma de las longitudes de los dos caminos, por qué se reduce en 2, porque hay dos lados con una capacidad de 2 y se agrega el costo de 1. Después de encontrar el costo máximo y el flujo máximo, si (<1.a>, <1.b>) no es un flujo completo, entonces no hemos encontrado suficientes rutas para 2 (tal vez 1 o 0), por lo que no hay solución.

[Otra solución al problema]

El clásico problema de programación dinámica multiproceso.

#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);
}

Supongo que te gusta

Origin blog.csdn.net/weixin_45697774/article/details/108555522
Recomendado
Clasificación