• HDU


    给定n * n矩阵C ij(1 <= i,j <= n),我们要找到0或1的n * n矩阵X ij(1 <= i,j <= n)。
    此外,X ij满足以下条件:
    1.X 12 + X 13 + ... X 1n = 1
    2.X 1n + X 2n + ... X n-1n = 1
    3.对于每个i(1 <i <n),满足ΣXki(1 <= k <= n)=ΣXij(1 <= j <= n)。
    例如,如果n = 4,我们可以得到以下等式:
    X 12 + X 13 + X 14 = 1
    X 14 + X 24 + X 34 = 1
    X 12 + X 22 + X 32 + X 42 = X 21 + X 22 + X 23 + X 24
    X 13 + X 23 + X 33 + X 43 = X 31 + X 32 + X 33 + X 34
    现在,我们想知道你可以得到的最小ΣCij * X ij(1 <= i,j <= n)。

    给定的性质可以想到以下等价变化:

       将xij转化为ij图的邻接矩阵。

       1号点在2-n中有一个为1,其余0,相当于出度为1,n号点同理,入度为1 。其余点随意。

       和C对应相乘相当于在C上找一条路径使得路径和最小。这样就转化成了最短路。

      考虑最短路满足的条件 1.1-n的最短路 2.1到1的一个环,n到n的一个环,两者的叠加。

      对于后者,只需要for一遍所有节点用已知的最短路维护即可,

    int n, m;//n点数 m边数
    struct edge { int v, w; edge(int a, int b) { v = a, w = b; } };//v终点,w边权
    struct node {
        int id, dis;//id点编号 dis暂时距离
        node(int a, int b) { id = a, dis = b; }
        friend bool operator<(node a, node b) {
            return a.dis > b.dis;//每次让距离小出队
        }
    };
    vector<edge>e[maxn];
    int dis[maxn];//记录最短路
    bool done[maxn];//记录是否找到最短路
    int Min1, Min2;
    
    
    void dijkstra(int t) {
        int s = t;//s起点 根据情况改
        for (int i = 0; i <= n; i++) dis[i] = INF, done[i] = 0;
        dis[s] = 0;
        priority_queue<node>Q;
        Q.push(node(s, 0));
        while (!Q.empty()) {
            node u = Q.top(); Q.pop();
            if (done[u.id])continue;
            done[u.id] = 1;
            for (int i = 0; i < e[u.id].size(); i++) {//遍历邻居
                edge y = e[u.id][i];
                if (done[y.v])continue;
                if (dis[y.v] > y.w + dis[u.id]) {
                    dis[y.v] = y.w + u.dis;
                    Q.push(node(y.v, dis[y.v]));//更新最短路
                }
            }
        }
        if (t == 0) {
            for (int i = 0; i < n; i++) {
                if (i == t) continue;
                Min1 = min(Min1, dis[i] + e[i][t].w);
            }
        }
        else {
            for (int i = 0; i < n; i++) {
                if (i == t) continue;
                Min2 = min(Min2, dis[i] + e[i][t].w);
            }
        }
    }
    
    
    int main() {
        int res;
        int x;
        while (~scanf("%d", &n)) {
            Min1 = Min2 = INF;
            memset(e, 0, sizeof e);
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < n; j++) x = readint(), e[i].push_back(edge(j, x));
            }
            for (int i = 0; i < n; i++) e[i][i].w = INF;
            dijkstra(0);
            res = dis[n - 1];
            dijkstra(n - 1);
            printf("%d", min(res, (Min1 + Min2)));
            puts("");
        }
    }
  • 相关阅读:
    Spring 控制器层如何调用DAO层
    Spring 工程分层
    spring boot工程如何启用 热启动功能
    Spring 视图层如何显示验证消息提示
    Sping POJO中如何添加验证规则和验证消息提示
    Spirng 分层,增加数据访问对象层
    Spring A 标签链接使用
    Spring 控制器重定向
    课程详情页之后台
    课程详情页之前台
  • 原文地址:https://www.cnblogs.com/hznumqf/p/13451552.html
Copyright © 2020-2023  润新知