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;
    }
  • 相关阅读:
    服务器架构前面加了防火墙,Nginx如何获取客户端真实ip???
    Prometheus学习笔记(5)Grafana可视化展示
    Prometheus学习笔记(4)什么是pushgateway???
    Prometheus学习笔记(3)什么是node_exporter???
    Prometheus学习笔记(2)Prometheus部署
    Prometheus学习笔记(1)Prometheus架构简介
    Centos 7 中的ulimit -n 65535 对进程的文件句柄限制不生效??
    Jenkins实用发布与回滚PHP项目生产实践
    Ansible入门笔记(3)之Playbook
    Ansible入门笔记(2)之常用模块
  • 原文地址:https://www.cnblogs.com/romaLzhih/p/9489837.html
Copyright © 2011-2022 走看看