http://acm.hdu.edu.cn/showproblem.php?pid=5639
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.
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.
For each test case, output the minimum number of deletion needed.
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
1
2
1
给你一个图,你每次可以选择一些边删除
要求你选择出来的边构成的图,每个连通块内最多构成一个环。
问你最少删除几次
考虑每个连通块内只有一个环的这个图是啥。
这是环套树,环套树有另外一个表示方法:
对于每一个点,他的边是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);
}
}