zoukankan      html  css  js  c++  java
  • HDU 5452(离线LCA,树形dp

    题目:给出一个图和它的一个生成树,要求删除生成树上的一条边和若干其他边,使得图不连通。求能删除的最小边数。

    思路:考虑dp,对于树上的一条边,删除之后,还需要删除的边的数目就是从这个节点的子树连向其他子树或祖先节点的边数。那么对于一棵子树来说这个统计数目就等于其子树的数目之和减去它的子树之间的边数。减的这一部分可以在tarjan离线LCA算法中实现。

    /*
    * @author:  Cwind
    */
    //#pragma comment(linker, "/STACK:102400000,102400000")
    #include <iostream>
    #include <map>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <functional>
    #include <set>
    #include <cmath>
    using namespace std;
    #define IOS std::ios::sync_with_stdio (false);std::cin.tie(0)
    #define pb push_back
    #define PB pop_back
    #define bk back()
    #define fs first
    #define se second
    #define sq(x) (x)*(x)
    #define eps (1e-6)
    #define IINF (1<<29)
    #define LINF (1ll<<59)
    #define INF (1000000000)
    #define FINF (1e3)
    typedef long long ll;
    typedef unsigned long long ull;
    typedef pair<int,int> pii;
    typedef pair<ll,ll> P;
    
    const int maxn=2e4+399;
    const int maxm=2e5+3909;
    int tt;
    vector<int> G[maxn],T[maxn];
    int n,m;
    int cas=0;
    int fa[maxn];
    int num[maxn];
    bool vis[maxn];
    int find(int x){
        if(fa[x]==x) return x;
        return fa[x]=find(fa[x]);
    }
    void init(){
        for(int i=0;i<=n;i++){
            fa[i]=i;
            num[i]=vis[i]=0;
        }
        for(int i=0;i<=n;i++){
            G[i].clear();
            T[i].clear();
        }
    }
    
    void dfs(int v,int f){
        vis[v]=1;
        for(int i=0;i<T[v].size();i++){
            int u=T[v][i];
            if(u==f) continue;
            dfs(u,v);
            num[v]+=num[u];
            fa[u]=v;
        }
        for(int i=0;i<G[v].size();i++){
            int u=G[v][i];
            if(u==f) continue;
            num[v]++;
            if(vis[u]) num[find(u)]-=2;
        }
    }
    int main(){
        freopen("/home/files/CppFiles/in","r",stdin);
        //freopen("test.in","r",stdin);
        //freopen("test.out","w",stdout);
        cin>>tt;
        while(tt--){
            cin>>n>>m;
            init();
            for(int i=0;i<m;i++){
                int a,b;
                scanf("%d%d",&a,&b);
                if(i<n-1) T[a].pb(b),T[b].pb(a);
                else G[a].pb(b),G[b].pb(a);
            }
            dfs(1,-1);
            int ans=1e9;
            for(int i=2;i<=n;i++){
                ans=min(ans,num[i]);
            }
            if(n==1) ans=-1;
            printf("Case #%d: %d
    ",++cas,ans+1);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    OpenCV 实现图像拼接例子
    XML 可扩展标记语言
    XML和YAML的区别与使用方法
    OpenCV 感兴趣区域ROI和logo添加技术
    OpenCV 详解掩膜mask
    OpenCV 读写xml和yml文件
    OpenCV 如何生成能在无OpenCV环境下运行的exe
    OpenCV 图像拼接和图像融合技术
    OpenCV 特征检测和特征匹配方法汇总
    OpenCV 图像矫正技术深入探讨
  • 原文地址:https://www.cnblogs.com/Cw-trip/p/4826917.html
Copyright © 2011-2022 走看看