zoukankan      html  css  js  c++  java
  • Codeforces667D(spfa+dp)

    题意:
    给定一个带权有向图,若P(A,B)表示节点A到B的最短路长度,选择四个节点ABCD,使得P(A,B)+P(B,C)+P(C,D)最大。
    节点数n在1,000以内,边数m在2,000以内。
    思路:
    首先先将两两点之间的最短路都算出来。
    之后建立pre和next两个数组,但在这里我用结构体保存其权值和编号一直算不出正确结果,退而求其次,只保存最长路径排名前三的结点,每次遇到一个更长的边,就将另外两条边往后推一个位置,给新的最长边留出位置。
    在枚举的时候,当最长边不存在的时候、最长边对应的点与b、c点冲突的时候,两个最长边对应的点彼此冲突的时候,跳过此次枚举。
    最后直接输出对应的结果编号即可。

    #include<cstdio>
    #include<vector>
    #include<queue>
    using namespace std;
    
    const int inf = 99999999;
    const int maxn = 10000 + 5;
    
    struct edge { 
        int v, w; 
    };
    int nex[maxn][3], pre[maxn][3];
    vector<vector<edge>>a;
    int n, m, dis[maxn][maxn];
    bool flag[maxn][maxn];
    
    void add_edge(int u, int v, int w) {
        edge tmp;
        tmp.v = v;
        tmp.w = w;
        a[u].push_back(tmp);
    }
    
    void spfa(int s) {
        queue<int>q;
        q.push(s);
        dis[s][s] = 0; flag[s][s] = true;
        while (!q.empty()) {
            int u = q.front(); q.pop(); flag[s][u] = false;
            for (int i = 0; i < a[u].size(); i++) {//扫描所有邻接点
                if (dis[s][a[u][i].v] > dis[s][u] + a[u][i].w) {
                    dis[s][a[u][i].v] = dis[s][u] + a[u][i].w;
                    if (!flag[s][a[u][i].v]) {
                        q.push(a[u][i].v);
                        flag[s][a[u][i].v] = true;
                    }
                }
            }
        }
    }
    
    void upd() {
        for (int i = 1; i <= n; i++) {
            for (int j = 0; j < 3; j++) {
                nex[i][j] = -1; 
                pre[i][j] = -1;
            }
        }
        int i, j;
        for (i = 1; i <= n; i++){
            for (j = 1; j <= n; j++){
                if (dis[i][j] == inf) continue;
                if (nex[i][0] == -1 || dis[i][nex[i][0]]<dis[i][j]){
                    nex[i][2] = nex[i][1];
                    nex[i][1] = nex[i][0];
                    nex[i][0] = j;
                }
                else if (nex[i][1] == -1 || dis[i][nex[i][1]]<dis[i][j]){
                    nex[i][2] = nex[i][1];
                    nex[i][1] = j;
                }
                else if (nex[i][2] == -1 || dis[i][nex[i][2]]<dis[i][j]){
                    nex[i][2] = j;
                }
            }
        }
        for (i = 1; i <= n; i++){
            for (j = 1; j <= n; j++){
                if (dis[j][i] == inf) continue;
                if (pre[i][0] == -1 || dis[pre[i][0]][i]<dis[j][i]){
                    pre[i][2] = pre[i][1];
                    pre[i][1] = pre[i][0];
                    pre[i][0] = j;
                }
                else if (pre[i][1] == -1 || dis[pre[i][1]][i]<dis[j][i]){
                    pre[i][2] = pre[i][1];
                    pre[i][1] = j;
                }
                else if (pre[i][2] == -1 || dis[pre[i][2]][i]<dis[j][i]){
                    pre[i][2] = j;
                }
            }
        }
    }
    
    int main() {
        int u, v, w;
        scanf("%d%d", &n, &m);
        a.resize(maxn);
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                dis[i][j] = inf;
                flag[i][j] = false;
            }
        }
    
        for (int i = 1; i <= m; i++) {
            scanf("%d%d%d", &u, &v, &w);
            add_edge(u, v, w);
        }
        for (int i = 1; i <= n; i++) {
            spfa(i);
        }
        upd();
        int ans = 0, str[4];
        for (int b = 1; b <= n; b++) {
            for (int c = 1; c <= n; c++) {
                if (b == c || dis[b][c] == inf) continue;
                for (int k = 0; k < 3; k++) {
                    for (int l = 0; l < 3; l++) {
                        if (pre[b][k] == -1 || nex[c][l] == -1)continue;
                        if (pre[b][k] == b || pre[b][k] == c)continue;
                        if (nex[c][l] == b || nex[c][l] == c)continue;
                        if (pre[b][k] == nex[c][l])continue;
                        int tem = dis[pre[b][k]][b] + dis[b][c] + dis[c][nex[c][l]];
                        if (tem > ans)
                        {
                            ans = tem;
                            str[0] = pre[b][k]; str[3] = nex[c][l];
                            str[1] = b; str[2] = c;
                        }
                    }
                }
            }
        }
        printf("%d %d %d %d
    ", str[0], str[1], str[2], str[3]);
        return 0;
    }
  • 相关阅读:
    Zookeeper----1.基础知识
    UML图
    VUE入门3---axios
    VUE入门2---vue指令
    谁先执行?props还是data或是其他? vue组件初始化的执行顺序详解
    vue双向绑定原理分析
    HTML/CSS -- 浏览器渲染机制
    vue工作原理分析
    导入导出需求整理
    .NET 异步详解
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/9489837.html
Copyright © 2011-2022 走看看