zoukankan      html  css  js  c++  java
  • [CF796D] Police Stations

    Description

    给定一棵树,树上有一些点是关键点。一棵树是合法的当且仅当所有点离最近的关键点的距离不超过 (d),求最多能删除多少条边。

    Solution

    考虑从所有的关键点开始 BFS。假设当前位于点 (p),下一个要访问的点是 (q),若 (q) 被访问过而 ((p,q)) 这条边未被访问过,则这条边可以被删除。

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long 
    const int N = 1000005;
    
    int n;
    int k;                          // 关键点个数
    int d;                          // 距离限制
    int vis[N];                     // 点是否被访问过
    unordered_set <int> eVis;       // 边是否被访问过
    unordered_set <int> eSrc;       // E
    unordered_set <int> eAns;       // 可以删除的边的集合
    unordered_map <int,int> eInd;   // 边的序号
    vector <int> keyVertex;         // 关键点
    
    int edgeId(int u,int v)         // 获取边的编码
    {
        if(u>v) swap(u,v);
        return u*N+v;
    }
    
    void setEdgeVis(int u,int v) 
    {
        eVis.insert(edgeId(u,v));
    }
    
    int getEdgeVis(int u,int v)
    {
        if(eVis.find(edgeId(u,v))==eVis.end()) return false;
        return true;
    }
    
    vector <int> g[N];
    
    struct BFSData      // BFS 队列中的信息
    {
        int p;          // 当前点下标
        int dist;       // 到出发点的距离
    };
    
    void bfs()
    {
        queue <BFSData> que;
        for(auto p:keyVertex)
        {
            que.push({p,0});
            vis[p]=1;
        }
        while(!que.empty())
        {
            int p=que.front().p;
            int dist=que.front().dist;
            que.pop();
            if(dist==d) continue;
            for(auto q:g[p]) 
            {
                if(vis[q] && !getEdgeVis(p,q))
                {
                    eAns.insert(edgeId(p,q));
                }
                if(!vis[q])
                {
                    que.push({q,dist+1});
                    setEdgeVis(p,q);
                    vis[q]=1;
                }
            }
        }
    }
    
    signed main()
    {
        cin>>n>>k>>d;
        for(int i=1;i<=k;i++)
        {
            int tmp;
            cin>>tmp;
            keyVertex.push_back(tmp);
        }
        for(int i=1;i<n;i++)
        {
            int u,v;
            cin>>u>>v;
            g[u].push_back(v);
            g[v].push_back(u);
            eInd[edgeId(u,v)]=i;
            eSrc.insert(edgeId(u,v));
        }
    
        bfs();
    
        for(auto i:eSrc)
        {
            if(eVis.find(i)==eVis.end()) 
            {
                eAns.insert(i);
            }
        }
    
        cout<<eAns.size()<<endl;
        for(auto i:eAns)
        {
            cout<<eInd[i]<<" ";
        }
        return 0;
    }
    
  • 相关阅读:
    ACM训练计划
    动态规划 最长公共子序列LCS
    Floyd最短路
    邻接表拓扑排序
    数字三角形(数塔) DP入门
    hdu 5533 计算几何 判断是否为正方形
    威尔逊定理--HDU2973
    二分--POJ-3258
    01背包--hdu2639
    矩阵快速幂--51nod-1242斐波那契数列的第N项
  • 原文地址:https://www.cnblogs.com/mollnn/p/13846794.html
Copyright © 2011-2022 走看看