zoukankan      html  css  js  c++  java
  • HDU 5639 Deletion 二分+网络流

    Deletion

    题目连接:

    http://acm.hdu.edu.cn/showproblem.php?pid=5639

    Description

    There is an undirected graph G with n vertices and m edges. Every time, you can select several edges and delete them. The edges selected must meet the following condition: let G′ be graph induced from these edges, then every connected component of G′ has at most one cycle. What is the minimum number of deletion needed in order to delete all the edges.

    Input

    There are multiple test cases. The first line of input contains an integer T indicating the number of test cases. For each test case:

    The first line contains two integers n and m (1≤n≤2000,0≤m≤2000) -- the number of vertices and the number of edges.

    For the next m lines, each line contains two integers ui and vi, which means there is an undirected edge between ui and vi (1≤ui,vi≤n,ui≠vi).

    The sum of values of n in all test cases doesn't exceed 2⋅104. The sum of values of m in all test cases doesn't exceed 2⋅104.

    Output

    For each test case, output the minimum number of deletion needed.

    Sample Input

    3
    4 2
    1 2
    1 3
    4 5
    1 2
    1 3
    1 4
    2 3
    2 4
    4 4
    1 2
    2 3
    3 4
    4 1

    Sample Output

    1
    2
    1

    Hint

    题意

    给你一个图,你每次可以选择一些边删除

    要求你选择出来的边构成的图,每个连通块内最多构成一个环。

    问你最少删除几次

    题解:

    考虑每个连通块内只有一个环的这个图是啥。

    这是环套树,环套树有另外一个表示方法:

    对于每一个点,他的边是i,f[i],这样n条边所构成的图,一定是环套树。

    相当于每条边(u,v),可以作为u->v,也可以作为v->u

    所以最终的答案就是【所有点的出度的最大值】的最小值

    然后这个东西用网络流+二分就好了。

    瞎比跑一下就好了。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN=100000,MAXM=100000,inf=1e9;
    struct Edge
    {
        int v,c,f,nx;
        Edge() {}
        Edge(int v,int c,int f,int nx):v(v),c(c),f(f),nx(nx) {}
    } E[MAXM];
    int G[MAXN],cur[MAXN],pre[MAXN],dis[MAXN],gap[MAXN],N,sz;
    void init(int _n)
    {
        N=_n,sz=0; memset(G,-1,sizeof(G[0])*N);
    }
    void link(int u,int v,int c)
    {
        E[sz]=Edge(v,c,0,G[u]); G[u]=sz++;
        E[sz]=Edge(u,0,0,G[v]); G[v]=sz++;
    }
    bool bfs(int S,int T)
    {
        static int Q[MAXN]; memset(dis,-1,sizeof(dis[0])*N);
        dis[S]=0; Q[0]=S;
        for (int h=0,t=1,u,v,it;h<t;++h)
        {
            for (u=Q[h],it=G[u];~it;it=E[it].nx)
            {
                if (dis[v=E[it].v]==-1&&E[it].c>E[it].f)
                {
                    dis[v]=dis[u]+1; Q[t++]=v;
                }
            }
        }
        return dis[T]!=-1;
    }
    int dfs(int u,int T,int low)
    {
        if (u==T) return low;
        int ret=0,tmp,v;
        for (int &it=cur[u];~it&&ret<low;it=E[it].nx)
        {
            if (dis[v=E[it].v]==dis[u]+1&&E[it].c>E[it].f)
            {
                if (tmp=dfs(v,T,min(low-ret,E[it].c-E[it].f)))
                {
                    ret+=tmp; E[it].f+=tmp; E[it^1].f-=tmp;
                }
            }
        }
        if (!ret) dis[u]=-1; return ret;
    }
    int dinic(int S,int T)
    {
        int maxflow=0,tmp;
        while (bfs(S,T))
        {
            memcpy(cur,G,sizeof(G[0])*N);
            while (tmp=dfs(S,T,inf)) maxflow+=tmp;
        }
        return maxflow;
    }
    int n,m;
    pair<int,int> p[2050];
    bool check(int x)
    {
        int s=0,t=4002;
        init(4005);
        for(int i=1;i<=m;i++)
        {
            link(s,i+n,1);
            link(i+n,p[i].first,1);
            link(i+n,p[i].second,1);
        }
        for(int i=1;i<=n;i++)
            link(i,t,x);
        return dinic(s,t)==m;
    }
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%d",&n,&m);
            for(int i=1;i<=m;i++)
                scanf("%d%d",&p[i].first,&p[i].second);
            int l=0,r=m,ans=0;
            while(l<=r)
            {
                int mid=(l+r)/2;
                if(check(mid))r=mid-1,ans=mid;
                else l=mid+1;
            }
            printf("%d
    ",ans);
        }
    }
  • 相关阅读:
    XRP共识算法
    瑞波币交易
    Bitcoin区块验证
    Bitcoin挖矿
    Bitcoin区块链攻击方式
    Bitcoin交易及验证
    C# 《编写高质量代码改善建议》整理&笔记 --(五)类型设计
    C# 《编写高质量代码改善建议》整理&笔记 --(五)成员设计
    C# 《编写高质量代码改善建议》整理&笔记 --(四)资源管理&序列化
    C# 《编写高质量代码改善建议》整理&笔记 --(三)泛型&委托&事件
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5246222.html
Copyright © 2011-2022 走看看