• [USACO19JAN]Shortcut题解


    本题算法:最短路树
    这是个啥玩意呢,就是对于一个图,构造一棵树,使从源点开始的单源最短路径与原图一模一样。怎么做呢,跑一边Dijkstra,然后对于一个点u,枚举它的边,设当前的边为cur_edge,如果dis[u]+cue_edge的长度=dis[cur_edge的终点],那么显然这条边应该珂以是最短路树上的一条边,然后打一个标记表示cur_edge的终点不能再被加边了,题目要求字典序最小,显然u从1到n枚举珂以解决问题。
    建好树以后跑一边DFS,我们知道当前节点u上连边的贡献是((dis[u] - t) imes)(u)为根的子树的牛的个数,找到贡献最大的点更新答案即可。

    代码:

    #include <cstdio>
    #include <queue>
    #include <algorithm>
    #include <set>
    #include <map>
    #define ll long long
    
    using namespace std;
    
    ll read(){
        ll x = 0; int zf = 1; char ch = ' ';
        while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
        if (ch == '-') zf = -1, ch = getchar();
        while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); return x * zf;
    }
    
    struct Edge{
        int from, to, next; ll dis;
    } edges[1000001];
    
    int head[300001], edge_num = 0;
    
    ll dis[300001];
    
    inline void addEdge(int u, int v, ll w){
        edges[++edge_num] = (Edge){u, v, head[u], w};
        head[u] = edge_num;
    }
    
    set< pair<ll, int> > que;
    int n, t, s = 1;
    
    void dijkstra(){
        for (int i = 1; i <= n; ++i)
            dis[i] = (1ll << 62);
        dis[s] = 0; que.insert(make_pair(0, s));
        pair<ll, int> uu; int u, v;
        while (!que.empty()){
            uu = *que.begin(); que.erase(uu);
            u = uu.second;
            for (int c_e = head[u]; c_e; c_e = edges[c_e].next){
                v = edges[c_e].to;
                if (dis[u] + edges[c_e].dis < dis[v]){
                    que.erase(make_pair(dis[v], v));
                    dis[v] = dis[u] + edges[c_e].dis;
                    que.insert(make_pair(dis[v], v));
                }
            }
        }
    }
    
    vector<int> vec[100001];
    ll ans = 0;
    int a[100001];
    int vis[100001];
    
    int DFS(int u){
        int v, cnt = 0; vis[u] = 1;
        for (int i = 0; i < vec[u].size(); ++i){
            v = vec[u][i];
            if (!vis[v])
                cnt += DFS(v);
        }
        cnt += a[u];
        ans = max(ans, (dis[u] - t) * cnt);
        return cnt;
    }
    
    int v2[100001];
    
    signed main(){
        int m; n = read(), m = read(), t = read();
        for (int i = 1; i <= n; ++i) a[i] = read();
        int u, v; ll w;
        for (int i = 1; i <= m; ++i){
            u = read(), v = read(), w = read();
            addEdge(u, v, w), addEdge(v, u, w);
        }
        dijkstra();
        for(int i = 1; i <= n; ++i)
            for(int c_e = head[i]; c_e; c_e = edges[c_e].next)
                if(dis[edges[c_e].to] == dis[i] + edges[c_e].dis && !v2[edges[c_e].to]){
                    v2[edges[c_e].to] = 1;
                    vec[i].push_back(edges[c_e].to), vec[edges[c_e].to].push_back(i);
                }
        DFS(1);
        printf("%lld", ans);
        return 0;
    }
    
  • 相关阅读:
    【JS】限制两个或多个单选框最多只能选择一个
    Markdown基本语法
    【thinkphp5】 分页样式修改
    Vscode 修改为中文语言
    【linux】Crontab 定时任务 使用实例
    【微信开发】 模板消息发送
    二维数组转化为字符串,中间用,隔开
    【golang】 go语言之环境搭建+ 第一个go语言程序
    【PHPstudy】安装Composer
    【LNMP】基于阿里云的https免费证书配置
  • 原文地址:https://www.cnblogs.com/linzhengmin/p/11039674.html
Copyright © 2020-2023  润新知