zoukankan      html  css  js  c++  java
  • 秘密的牛奶运输 题解

    题目连接

    分析

    一道可以暴力水过去的次小生成树

    • step1

    首先用(Kruskal)||(Prim)求出原图的一颗最小生成树,在连边的时候,用一个(vis)记录一下那些已经在最小生成树里面。

    • step2

    提前暴力(dfs)或者(bfs)求出任意两点构成的环之间的最大权值

    具体操作

    定义函数(dfs(int s, int u, int father, int mw1, int mw2))
    s -> 起点 u -> 终点 father 判断是否回到原起点 mw1 最大值 mw2 次大值
    再用md1[s][u]保存从s -> u的最大边权值, 用md2[s][u]保存从s -> u的次大边权值
    循环遍历与重点u相连接的每一个点(v),如果没有回到father就继续。
    定义t1, t2
    如果 从u -> v的 权值(w) 大于了现在的mw1
    - 把t1 更新为 w
    - 把t2 更新为 mw1
    否则 如果 w 大于了现在的mw2 并且小于 mw1
    - 把t1 更新为 mw1
    - 把t2 更新为 w
    最后递归遍历 dfs(s, v, u, t1, t2)

    • step2

    再一次考虑每一条非树边,用这条边上的权值考虑替换原边

    END

    代码

    #include <queue>
    #include <vector>
    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    const int MAXN = 505;
    const int MAXM = 1e4 + 5;
    
    long long n, m, tot, fa[MAXN], md1[MAXN][MAXN], md2[MAXN][MAXN];
    long long ans, sum;
    bool vis[MAXN];
    
    struct node {
        long long u, v, w;
        bool vis;
    } dis[MAXM];
    bool cmp(node x, node y) {
        return x.w < y.w;
    }
    
    struct edge {
        int v, w;
        edge() {}
        edge(int V, int W) {
            v = V;
            w = W;
        }
    };
    
    vector<edge> G[MAXN];
    
    void AddEdge(int u, int v, long long w) { G[u].push_back(edge(v, w)); }
    
    int FindSet(int v) {
        if (fa[v] == v)
            return fa[v];
        else
            return fa[v] = FindSet(fa[v]);
    }
    bool UnionSet(int u, int v) {
        int x = FindSet(u);
        int y = FindSet(v);
        if (x == y)
            return 0;
        else {
            fa[x] = fa[y];
            return 1;
        }
    }
    
    void dfs(int s, int u, int fa, int mw1, int mw2) {
    	md1[s][u] = mw1;
    	md2[s][u] = mw2;
    	for (int j = 0; j < G[u].size(); j++) {
    		int v = G[u][j].v;
    		int w = G[u][j].w;
    		if (v != fa) {
    			int t1, t2;
    			if (w > mw1) {
    				t1 = w;
    				t2 = mw1;
    			} else if (w < mw1 && w > mw2) {
    				t1 = mw1;
    				t2 = w;
    			}
    			dfs (s, v, u, t1, t2);
    		}
    	}
    } 
    void Kruskal() {
        for (int i = 1; i <= n; i++) fa[i] = i;
        sort(dis + 1, dis + 1 + m, cmp);
        for (int i = 1; i <= m; i++) {
            if (UnionSet(dis[i].u, dis[i].v)) {
                sum += dis[i].w;
                tot++;
                dis[i].vis = 1;
                AddEdge(dis[i].u, dis[i].v, dis[i].w);
                AddEdge(dis[i].v, dis[i].u, dis[i].w);
            }
            if (tot == n - 1)
                break;
        }
        for (int i = 1; i <= n; i++) {
        	dfs (i, i, -1, 0, 0);
        }
        ans = 1e19;
        for (int i = 1; i <= m; i++) {
    	if (dis[i].vis == 0) {
    		int w = dis[i].w, u = dis[i].u, v = dis[i].v;
    		if (w > md1[u][v]) ans = min(ans, sum + w - md1[u][v]);
    		else if (w > md2[u][v]) ans = min(ans, sum + w - md2[u][v]);
    	}
        }
        printf ("%lld
    ", ans);
    }
    
    int main() {
        scanf("%lld %lld", &n, &m);
        for (int i = 1; i <= m; i++) {
            scanf ("%lld %lld %lld", &dis[i].u, &dis[i].v, &dis[i].w);
        }
        Kruskal();
        return 0;
    }
    
  • 相关阅读:
    Angular 学习笔记 (Material table sticky 原理)
    Asp.net core 学习笔记 ( ef core transaction scope & change level )
    sql server 学习笔记 (nested transaction 嵌套事务)
    html 图片文字并排显示
    Maven 的配置
    Eclipse的配置
    tomcat 的安装与配置
    java jdk的安装与配置
    javascript 拖拽
    html5 CSS input placeholder兼容性处理
  • 原文地址:https://www.cnblogs.com/cqbz-ChenJiage/p/13513932.html
Copyright © 2011-2022 走看看