ABC 喵喵喵
D
数学归纳吖!
- n=0 ok
- n=1 ok 形成d[1]+1个点的完全图
- n>2 一定能到达比n更小的状态
d[n],d[n-1]....d[1] -> d[n-1]-d[1],d[n-2]-d[1],...d[2]-d[1]
E
- 不考虑A操作,只考虑B操作:排序+贪心。
- 考虑A操作,会发现a全部加到一个人身上是最好的。
- 枚举把a加到哪个人头上。
F
二分图的最小边覆盖 = V - MaxMatch
- 最大匹配前是个负号哎!那没有被最大流浸泡过的边会不会就是答案呢?
- Hint:源点向左集连容量为
deg-k
的边
code
#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
#include <vector>
using namespace std;
const int N = 5000 + 10;
const int INF = 1e9 + 7;
#define mp(x,y) make_pair(x,y)
struct Edge {
int from , to , cap , flow, id;
};
bool visit[N];
struct Dinic {
int n,m,s,t;
vector<Edge> edges;
vector<int> f[N];
bool vis[N];
int d[N];
int cur[N];
void init(int n) {
this->n = n;
edges.clear();
for (int i = 0; i < N; i ++) f[i].clear();
memset(d, 0, sizeof(d));
memset(cur, 0, sizeof(cur));
memset(visit, 0, sizeof(visit));
}
void AddEdge(int from,int to,int cap,int id)
{
edges.push_back((Edge){from,to,cap,0,id});
edges.push_back((Edge){to,from,0,0,id});
m = edges.size();
f[from].push_back(m-2);
f[to].push_back(m-1);
}
bool BFS()
{
memset(vis,0,sizeof(vis));
queue<int> q;
q.push(s);
d[s] = 0;
vis[s] = 1;
while(!q.empty())
{
int x = q.front(); q.pop();
for(int i=0;i<f[x].size();i++)
{
Edge &e = edges[f[x][i]];
//cout<<"to="<<e.to<<"from="<<e.from<<' '<<e.flow<<' '<<e.cap<<' '<<vis[e.to]<<endl;
if(!vis[e.to] && e.flow < e.cap) //只考虑残留网络中的弧
{
vis[e.to] = 1;
d[e.to] = d[x] + 1;//层次图
q.push(e.to);
}
}
}
return vis[t];//能否到汇点,不能就结束
}
int DFS(int x,int a)//x为当前节点,a为当前最小残量
{
if(x == t || a == 0) return a;
int flow = 0 , r;
for(int& i = cur[x];i < f[x].size();i++)
{
Edge& e = edges[f[x][i]];
if(d[x] + 1 == d[e.to] && (r = DFS(e.to , min(a,e.cap - e.flow) ) ) > 0 )
{
e.flow += r;
edges[f[x][i] ^ 1].flow -= r;
//get Ans
//printf("miao: %d
", edges[f[x][i] ^ 1].id);
//visit[edges[f[x][i] ^ 1].id] = 1;
flow += r;//累加流量
a -= r;
if(a == 0) break;
}
}
return flow;
}
int MaxFlow(int s,int t)
{
this->s = s; this->t = t;
int flow = 0;
while(BFS())
{
memset(cur,0,sizeof(cur));
flow += DFS(s,INF);
//printf("%d
", flow);
}
for (int i=0;i<edges.size();i++) {
if (edges[i].flow) visit[edges[i].id] = 1;
}
return flow;
}
} G;
int n1,n2,m,deg[N];
vector< pair<int, int> > v[N];
void build_gragh(int k) {
int S = n1+n2+1, T=n1+n2+2;
G.init(T+2);
for(int i=1;i<=n1;i++) {
G.AddEdge(S,i,deg[i]-k,0);
}
for(int i=1;i<=n2;i++) {
G.AddEdge(i+n1,T,deg[i+n1]-k,0);
}
for(int i=1;i<=n1;i++) {
for (int j=0;j<v[i].size();j++) {
G.AddEdge(i,v[i][j].first+n1,1,v[i][j].second);
}
}
int ret = G.MaxFlow(S,T);
printf("%d ", m-ret);
for (int i=1;i<=m;i++) {
if (visit[i] == 0)
printf("%d ", i);
}
printf("
");
}
int main() {
scanf("%d%d%d",&n1,&n2,&m);
for(int i=1;i<=m;i++) {
int x, y;
scanf("%d%d",&x,&y);
v[x].push_back(mp(y, i));
deg[x] ++, deg[n1+y]++;
}
printf("0
");
int mnDegree = *min_element(deg+1,deg+1+n1+n2);
for (int i = 1; i <= mnDegree; i ++) {
build_gragh(i);
}
}