• Codeforces1076D. Edge Deletion(最短路树+bfs)


    题目链接:传送门

    题目:

    D. Edge Deletion
    time limit per test
    2.5 seconds
    memory limit per test
    256 megabytes
    input
    standard input
    output
    standard output
    
    You are given an undirected connected weighted graph consisting of n
    vertices and m edges. Let's denote the length of the shortest path from vertex 1 to vertex i as di
    
    .
    
    You have to erase some edges of the graph so that at most k
    edges remain. Let's call a vertex i good if there still exists a path from 1 to i with length di
    
    after erasing the edges.
    
    Your goal is to erase the edges in such a way that the number of good vertices is maximized.
    Input
    
    The first line contains three integers n
    , m and k (2≤n≤3105, 1≤m≤3105, n−1≤m, 0≤k≤m
    
    ) — the number of vertices and edges in the graph, and the maximum number of edges that can be retained in the graph, respectively.
    
    Then m
    lines follow, each containing three integers x, y, w (1≤x,y≤n, x≠y, 1≤w≤109), denoting an edge connecting vertices x and y and having weight w
    
    .
    
    The given graph is connected (any vertex can be reached from any other vertex) and simple (there are no self-loops, and for each unordered pair of vertices there exists at most one edge connecting these vertices).
    Output
    
    In the first line print e
    — the number of edges that should remain in the graph (0≤e≤k
    
    ).
    
    In the second line print e
    distinct integers from 1 to m
    
    — the indices of edges that should remain in the graph. Edges are numbered in the same order they are given in the input. The number of good vertices should be as large as possible.
    Examples
    Input
    Copy
    
    3 3 2
    1 2 1
    3 2 1
    1 3 3
    
    Output
    Copy
    
    2
    1 2 
    
    Input
    Copy
    
    4 5 2
    4 1 8
    2 4 1
    2 1 3
    3 4 9
    3 1 5
    
    Output
    Copy
    
    2
    3 2 
    View Code

    题目大意:

      一个图N个点M条双向边。设各点到点1的距离为di,保证满足条件删除M-K条边之后使得到点1的距离仍为di的点数量最多的情况下,输出剩余的K条边的编号(按输入顺序)。

       (2≤n≤3⋅105, 1≤m≤3⋅105, n−1≤m, 0≤k≤m)

    思路:

      用dijkstra跑出最短路树:

      松弛的时候用fat数组保存被松弛的点的父节点,用faEdge数组保存对应的边,这样就把整棵树保留下来了。

      然后在树上bfs,贪心地保留边就好了。(dfs、bfs都可以,反正是树,多一条边就多一个点)

    代码:

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const int MAX_N = 3e5 + 5;
    
    int N, M, K;
    struct PQNode{
        int v;
        ll dis;
        PQNode(int _v = 0, ll _dis = 0) : v(_v), dis(_dis) {}
        bool operator < (const PQNode& x) const {
            return dis > x.dis;
        }
    };
    struct Edge{
        int id, v;
        ll w;
        Edge(int _id = 0, int _v = 0, ll _w = 0) : id(_id), v(_v), w(_w) {}
    };
    vector <Edge> E[MAX_N];
    void addEdge(int i, int u, int v, ll w) {
        E[u].push_back(Edge(i, v, w));
        E[v].push_back(Edge(i, u, w));
    }
    bool vis[MAX_N];
    ll dist[MAX_N];
    int fat[MAX_N], faEdge[MAX_N];
    priority_queue <PQNode> PQ;
    void Dijkstra()
    {
        memset(dist, 0x3f, sizeof dist);
        memset(vis, false, sizeof vis);
        dist[1] = 0;
        fat[1] = 1;
        PQ.push(PQNode(1, 0));
        while (!PQ.empty()) {
            int u = PQ.top().v;
            PQ.pop();
            if (vis[u])
                continue;
            vis[u] = true;
            for (int i = 0; i < (int)E[u].size(); i++) {
                int id = E[u][i].id;
                int v = E[u][i].v;
                ll w = E[u][i].w;
                if (vis[v])
                    continue;
                if (dist[v] > dist[u] + w) {
                    dist[v] = dist[u] + w;
                    fat[v] = u;
                    faEdge[v] = id;
                    PQ.push(PQNode(v, dist[v]));
                }
            }
        }
    }
    
    vector <int> son[MAX_N];
    queue <int> BQ;
    vector <int> ans;
    void bfs()
    {
        BQ.push(1);
        while (!BQ.empty() && K > 0) {
            int u = BQ.front(); BQ.pop();
            for (int i = 0; i < (int)son[u].size(); i++) {
                int v = son[u][i];
                if (K > 0) {
                    ans.push_back(faEdge[v]);
                    BQ.push(v);
                    K--;
                }
                else
                    break;
            }
        }
    }
    
    int main()
    {
        cin >> N >> M >> K;
        for (int i = 1; i <= M; i++) {
            int u, v; ll w;
            scanf("%d%d%lld", &u, &v, &w);
            addEdge(i, u, v, w);
        }
        Dijkstra();
        for (int i = 2; i <= N; i++)
            son[fat[i]].push_back(i);
        bfs();
        cout << ans.size() << endl;
        bool firstprint = true;
        for (int i = 0; i < (int)ans.size(); i++) {
            if (firstprint)
                firstprint = false;
            else
                printf(" ");
            printf("%d", ans[i]);
        }
        puts("");
        return 0;
    }
    /*
    3 3 2
    1 2 1
    3 2 1
    1 3 3
    */
    View Code

    比赛代码(改的模板,所以写的有点乱,待我回去整理一下)

    #include <bits/stdc++.h>
    
    using namespace std;
    typedef long long ll;
    const ll INF = 0x3f3f3f3f3f3f3f3f;
    const int maxn = 3e5 + 5;
    struct qnode{
        int v;
        ll c;
        int cnt;
        qnode(int _v = 0, ll _c = 0, int _cnt = 0) : v(_v), c(_c), cnt(_cnt) {}
        bool operator < (const qnode& r) const {
            if (c == r.c)
                return cnt > r.cnt;
            return c > r.c;
        }
    };
    struct Edge{
        int v;
        int id;
        ll cost;
        Edge(int _v = 0, int _id = 0, ll _cost = 0) : v(_v), id(_id), cost(_cost) {}
    };
    vector <Edge> E[maxn];
    bool vis[maxn];
    ll dist[maxn];
    int cnt[maxn];
    int fa[maxn], faedge[maxn];
    //点的编号从 1 开始
    void Dijkstra(int N)
    {
        memset(vis, false, sizeof (vis));
        for (int i = 1; i <= N; i++)
            dist[i] = INF, cnt[i] = maxn;
        priority_queue <qnode> Q;
        dist[1] = 0;
        cnt[1] = 0;
        fa[1] = 1;
        Q.push(qnode(1, 0));
        qnode tmp;
        while (!Q.empty()) {
            tmp = Q.top(); Q.pop();
            int u = tmp.v;
            if (vis[u])
                continue;
            vis[u] = true;
            for (int i = 0; i < (int)E[u].size(); i++) {
                int v = E[u][i].v;
                ll cost = E[u][i].cost;
                int id = E[u][i].id;
                if (!vis[v]) {
                    if (dist[v] > dist[u] + cost) {
                        dist[v] = dist[u] + cost;
                        cnt[v] = cnt[u] + 1;
                        fa[v] = u;
                        faedge[v] = id;
                        Q.push(qnode(v, dist[v], cnt[v]));
                    }
                    else if (dist[v] == dist[u] + cost && cnt[v] > cnt[u] + 1) {
                        cnt[v] = cnt[u] + 1;
                        fa[v] = u;
                        faedge[v] = id;
                        Q.push(qnode(v, dist[v], cnt[v]));
                    }
                }
            }
        }
    }
    void addedge(int u, int v, ll w, int i) {
        E[u].push_back(Edge(v, i, w));
        E[v].push_back(Edge(u, i, w));
    }
    
    int N, M, K;
    vector <int> son[maxn];
    queue <int> BQ;
    vector <int> ans;
    
    void bfs() {
        BQ.push(1);
        while (!BQ.empty() && K > 0) {
            int u = BQ.front(); BQ.pop();
            int len = son[u].size();
            for (int i = 0; i < len; i++) {
                int v = son[u][i];
                if (K > 0) {
                    K--;
                    ans.push_back(faedge[v]);
                    BQ.push(v);
                }
                else
                    break;
            }
        }
    }
    
    int main() {
        cin >> N >> M >> K;
        for (int i = 1; i <= M; i++) {
            int u, v;
            ll w;
            scanf("%d%d%lld", &u, &v, &w);
            addedge(u, v, w, i);
        }
        Dijkstra(N);
        for (int i = 2; i <= N; i++) {
            son[fa[i]].push_back(i);
        }
        bfs();
        int len = ans.size();
        cout << len << endl;
        bool firstprint = true;
        for (int i = 0; i < len; i++) {
            if (firstprint)
                firstprint = false;
            else
                printf(" ");
            printf("%d", ans[i]);
        }
        puts("");
        return 0;
    }
    View Code
  • 相关阅读:
    学习进度03
    构建之法阅读笔记03
    软件工程结队作业01
    用图像算法增强夜视效果
    python将指定目录下的所有文件夹用随机数重命名
    python脚本中调用其他脚本
    opencv+python实现图像锐化
    机器学习中减弱不同图像数据色调及颜色深浅差异
    python利用列表文件遍历
    python文件处理-检查文件名/路径是否正确
  • 原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/9951711.html
Copyright © 2020-2023  润新知