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\n",ans);
    }
}
    原文作者:qscqesze
    原文地址: https://www.cnblogs.com/qscqesze/p/5246222.html
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞