zoukankan      html  css  js  c++  java
  • UVa 1057

    先声明一下:这篇题解纯粹是对原题解的翻译与修复,并非原创。

    解法是 DP + 最短路。这个思想并不是很少见,而这题强化了 DP 的思维难度。

    设 f[i][j] 为 1~i,2~j 所经过的点数最少的路径的点数(考虑了重复点)。

    给出转移方程:

    f[i2][j] = min(f[i][j] + [i2 != j] | g[i][i2] = 1)

    f[i][j2] = min(f[i][j] + [i != j2] | g[j2][j] = 1)

    f[j][i] = min(f[j][i], f[i][j] + dis[i][j] - 1)

    (f 是 DP 数组,dis 为两点最短路,g 是邻接矩阵)

    初始化 f[1][1] = 1,那么答案就是 f[2][2]。

    反着来是类似的。

    #include <bits/stdc++.h>
    
    using namespace std;
    
    const int N = 100 + 5;
    const int INF = 0x3f3f3f3f;    
    
    int dis[N][N];
    int f[N][N];
    bool inq[N][N];
    vector<int> g1[N], g2[N];
    
    int main() {    
        int n, m, kase = 0;
        while (scanf("%d %d", &n, &m) == 2 && n) {
            for (int i = 1; i <= n; i++) {
                g1[i].clear();
                g2[i].clear();
            }
            memset(dis, INF, sizeof dis);
            for (int i = 1; i <= n; i++) {
                dis[i][i] = 0;
            }
            for (int i = 1; i <= m; i++) {
                int u, v;
                scanf("%d %d", &u, &v);
                dis[u][v] = 1;
                g1[u].push_back(v);
                g2[v].push_back(u);
            }
            for (int k = 1; k <= n; k++) {
                for (int i = 1; i <= n; i++) {
                    for (int j = 1; j <= n; j++) {
                        dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);
                    }
                }
            }
            printf("Network %d
    ", ++kase);
            if (dis[1][2] != INF && dis[2][1] != INF) {
                memset(f, INF, sizeof f);
                f[1][1] = 1;
                queue<int> q1, q2;
                q1.push(1);
                q2.push(1);
                inq[1][1] = true;
                while (!q1.empty()) {
                    int u1 = q1.front(), u2 = q2.front();
                    q1.pop(); q2.pop();
                    inq[u1][u2] = false;
                    for (int i = 0; i < g1[u1].size(); i++) {
                        int v1 = g1[u1][i];    
                        int cand = f[u1][u2] + (v1 != u2);
                        if (cand < f[v1][u2]) {
                            f[v1][u2] = cand;
                            if (!inq[v1][u2]) {
                                q1.push(v1);
                                q2.push(u2);
                                inq[v1][u2] = true;
                            }
                        }
                    }
                    for (int i = 0; i < g2[u2].size(); i++) {
                        int v2 = g2[u2][i];
                        int cand = f[u1][u2] + (v2 != u1);
                        if (cand < f[u1][v2]) {
                            f[u1][v2] = cand;
                            if (!inq[u1][v2]) {
                                q1.push(u1);
                                q2.push(v2);
                                inq[u1][v2] = true;
                            }
                        }
                    }
                    if (u1 != u2 && f[u1][u2] + dis[u1][u2] - 1 < f[u2][u1]) {
                        f[u2][u1] = f[u1][u2] + dis[u1][u2] - 1;
                        if (!inq[u2][u1]) {
                            q1.push(u2);
                            q2.push(u1);
                            inq[u2][u1] = true;
                        }
                    }
                }
                printf("Minimum number of nodes = %d
    ", f[2][2]);
            } else {
                printf("Impossible
    ");
            }
            printf("
    ");
        }
        return 0;
    }
    View Code
  • 相关阅读:
    (一) kinect概述
    (五)摇杆/按钮/触摸板
    (四)Trigger
    (三)快速添加touch事件
    (二)简单触控
    Java程序设计当堂测试 9.20
    Java程序设计当堂测试感受
    暑假生活第八周总结
    暑假生活第七周总结
    暑假生活第六周总结
  • 原文地址:https://www.cnblogs.com/HailJedi/p/9588256.html
Copyright © 2011-2022 走看看