题意:给一个二分图,存在重边,求使各点度数至少为k(0<=k<=min(d[i]))的最小边集合。
分析:首先建立一个源点s向二分图左边连边,建立一个汇点e,所有二分图右边的点向e点连边。要使每个点的度数大于等于k,可使流过每个点的流量小于等于d[i]-k。(d[i]为每个点的度数),就可以在建立源点到二分图左边点,和二分图右边点到汇点时开始限制。然后对每个k跑一遍最大流,记录一下剩余的边即是正确答案。
You are given a bipartite graph G = (U, V, E), U is the set of vertices of the first part, V is the set of vertices of the second part and E is the set of edges. There might be multiple edges.
Let's call some subset of its edges k-covering iff the graph has each of its vertices incident to at least k edges. Minimal k-covering is such a k-covering that the size of the subset is minimal possible.
Your task is to find minimal k-covering for each , where minDegreeis the minimal degree of any vertex in graph G.
Input
The first line contains three integers n1, n2 and m (1 ≤ n1, n2 ≤ 2000, 0 ≤ m ≤ 2000) — the number of vertices in the first part, the number of vertices in the second part and the number of edges, respectively.
The i-th of the next m lines contain two integers ui and vi (1 ≤ ui ≤ n1, 1 ≤ vi ≤ n2) — the description of the i-th edge, ui is the index of the vertex in the first part and vi is the index of the vertex in the second part.
Output
For each print the subset of edges (minimal k-covering) in separate line.
The first integer cntk of the k-th line is the number of edges in minimal k-covering of the graph. Then cntk integers follow — original indices of the edges which belong to the minimal k-covering, these indices should be pairwise distinct. Edges are numbered 1 through m in order they are given in the input.
Examples
3 3 7
1 2
2 3
1 3
3 2
3 3
2 1
2 1
0
3 3 7 4
6 1 3 6 7 4 5
1 1 5
1 1
1 1
1 1
1 1
1 1
0
1 5
2 4 5
3 3 4 5
4 2 3 4 5
5 1 2 3 4 5
#include<bits/stdc++.h> using namespace std; const int N=4010; vector<int>g[N],num[N],ans[N]; int f[N][N],tem[N][N],n,m,d[N],cnt,v[N]; bool dfs(int x) { if(x==n)return true; v[x]=cnt; for(int i=0;i<g[x].size();i++) { int y=g[x][i]; if(f[x][y]==0||v[y]==cnt)continue; if(dfs(y)) { f[x][y]--; f[y][x]++; return true; } } return false; } int main() { int n1,n2,x,y,k; scanf("%d%d%d",&n1,&n2,&k); n=n1+n2+1; for(int i=1;i<=k;i++) { scanf("%d%d",&x,&y); y+=n1; g[x].push_back(y); g[y].push_back(x); num[x].push_back(i); f[x][y]++; d[x]++,d[y]++; } m=k*2; for(int i=1;i<n;i++)m=min(m,d[i]); for(int i=1;i<=n1;i++) { g[0].push_back(i); g[i].push_back(0); f[0][i]=d[i]-m; } for(int i=n1+1;i<n;i++) { g[i].push_back(n); g[n].push_back(i); f[i][n]=d[i]-m; } for(int l=m;l>=0;l--) { cnt++; while(dfs(0))cnt++; for(int i=1;i<=n1;i++) { for(int j=0;j<g[i].size();j++) { y=g[i][j]; tem[i][y]=f[i][y]; } } for(int i=1;i<=n1;i++) { for(int j=0;j<g[i].size();j++) { y=g[i][j]; if(y&&tem[i][y]) { tem[i][y]--; ans[l].push_back(num[i][j]); } } } for(int i=1;i<=n1;i++)f[0][i]++; for(int i=n1+1;i<n;i++)f[i][n]++; } for(int i=0;i<=m;i++) { printf("%d",ans[i].size()); for(auto &x:ans[i]) printf(" %d",x); printf(" "); } }