• hdu 5452 Minimum Cut(打标记,lca,dfs)


    题目链接

    Minimum Cut

    Time Limit: 3000/2000 MS (Java/Others) Memory Limit: 65535/102400 K (Java/Others)
    Total Submission(s): 1816 Accepted Submission(s): 861

    Problem Description
    Given a simple unweighted graph G (an undirected graph containing no loops nor multiple edges) with n nodes and m edges. Let T be a spanning tree of G.
    We say that a cut in G respects T if it cuts just one edges of T.

    Since love needs good faith and hypocrisy return for only grief, you should find the minimum cut of graph G respecting the given spanning tree T.

    Input
    The input contains several test cases.
    The first line of the input is a single integer t (1≤t≤5) which is the number of test cases.
    Then t test cases follow.

    Each test case contains several lines.
    The first line contains two integers n (2≤n≤20000) and m (n−1≤m≤200000).
    The following n−1 lines describe the spanning tree T and each of them contains two integers u and v corresponding to an edge.
    Next m−n+1 lines describe the undirected graph G and each of them contains two integers u and v corresponding to an edge which is not in the spanning tree T.

    Output
    For each test case, you should output the minimum cut of graph G respecting the given spanning tree T.

    Sample Input
    1
    4 5
    1 2
    2 3
    3 4
    1 3
    1 4

    Sample Output
    Case #1: 2

    Source
    2015 ACM/ICPC Asia Regional Shenyang Online

    题意:

    给出一个 (n) 个点的无向图,(m) 条边,初始时先给出 (n-1) 条边,这些边能构成原图的一棵生成树,让后给 (m-n+1) 条边,定义原图的一个割是只删除原生成树上的一条边的割,求最小割的边数。

    题解:

    考虑砍掉每一条树边(转化为考虑删掉每个点和其与父节点连的边),对于非生成树上的树边 ((u,v)),求他们的 (lca) ,假设为 (f) ,那么 (cnt[f]-=2,cnt[u]++,cnt[v]++),这有点像打标记,然后对树进行一遍 (dfs) ,求出每个结点 (u) 的子树的 (cnt) 和,这就代表了删除 (u)(fa[u]) 这条边所需要删除的非父边数目,然后扫一遍求最小即可。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<stack>
    using namespace std;
    #define rep(i,a,n) for (int i=a;i<n;i++)
    #define per(i,a,n) for (int i=n-1;i>=a;i--)
    #define pb push_back
    #define fi first
    #define se second
    #define dbg(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<endl;
    typedef vector<int> VI;
    typedef long long ll;
    typedef pair<int,int> PII;
    const int maxn=2e4+100;
    int head[maxn];
    struct edge
    {
        int to,next;
    }e[maxn*2];   //
    int tol=0;
    void add(int u,int v)
    {
        e[++tol].to=v,e[tol].next=head[u],head[u]=tol;
    }
    int deep[maxn],fa[maxn][17];
    void bfs(int rt)
    {
        queue<int>q;
        deep[rt]=0;
        fa[rt][0]=rt;
        q.push(rt);
        while(!q.empty())
        {
            int t=q.front();
            q.pop();
            for(int i=1;i<=16;i++)
                fa[t][i] = fa[fa[t][i-1]][i-1];
            for(int i = head[t];i;i=e[i].next)
            {
                int v = e[i].to;
                if(v==fa[t][0])continue;
                deep[v]=deep[t]+1;
                fa[v][0]=t;
                q.push(v);
            }
        }
    }
    
    int lca(int u,int v)
    {
        if(deep[u]>deep[v])swap(u,v);
        int hu=deep[u],hv=deep[v];
        int tu=u,tv=v;
        for(int det = hv-hu, i = 0; det ;det>>=1, i++)
            if(det&1)
                tv = fa[tv][i];
        if(tu == tv)return tu;
        for(int i =16; i>=0; i--)
        {
            if(fa[tu][i] == fa[tv][i]) continue;
            tu = fa[tu][i];
            tv = fa[tv][i];
        }
        return fa[tu][0];
    }
    int cnt[maxn];
    void dfs(int u,int f)
    {
        for(int i=head[u];i;i=e[i].next)
        {
            int v=e[i].to;
            if(v==f) continue;
            dfs(v,u);
            cnt[u]+=cnt[v];
        }
    }
    int main()
    {
        int cas;
        scanf("%d",&cas);
        int t=0;
        while(cas--)
        {
            int n,m;
            scanf("%d%d",&n,&m);
            rep(i,1,n+1) head[i]=0,cnt[i]=0;
            tol=0;
            rep(i,1,n)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                add(u,v),add(v,u);
            }
            bfs(1);
            rep(i,0,m-n+1)
            {
                int u,v;
                scanf("%d%d",&u,&v);
                int f=lca(u,v);
                cnt[f]-=2;
                cnt[u]+=1,cnt[v]+=1;
            }
            dfs(1,0);
            int ans=1e9;
            rep(i,2,n+1) ans=min(ans,cnt[i]);
            ans++;
            printf("Case #%d: %d
    ",++t,ans);
        }
        return 0;
    }
    
  • 相关阅读:
    2017年7月10日 20:34:02 简易博客记录组
    Oracle审计表AUD$处理方法 (Z)
    Oracle中trace的几种(Z)
    查看oracle数据库是否归档和修改归档模式(转)
    oracle exp-000991
    基于公司级平台封装的SqlserverHelper
    pycharm运行测试程序提示no tests were found
    10-13 验证用户
    10-11 喜欢的数字
    10-1 Python 学习笔记
  • 原文地址:https://www.cnblogs.com/tarjan/p/7568351.html
Copyright © 2020-2023  润新知