洛谷 P2764 最小路径覆盖问题
裸题,直接上板子
#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 500 + 10;
const int maxm = 15000 + 10;
int n,m;
int l[maxn];//记录层数
int h[maxn];//链式前向星
int cur[maxn];
int tot = 0;
int nxt[maxn];
int vis[maxn];
struct edge
{
int to;
int c;
int next;
edge(int x = 0, int y = 0, int z = 0) : to(x), c(y), next(z) {}
}es[maxm*2];//记录边 注意是2倍
void add_edge(int u, int v, int c)
{
es[tot] = edge(v,c,h[u]);
h[u] = tot++;
es[tot] = edge(u,0,h[v]);
h[v] = tot++;
// cout << u <<" " <<v <<endl;
}
bool bfs(int s, int t)
{
memset(l,0,sizeof(l));
l[s] = 1;
queue <int> q;
q.push(s);
while(!q.empty())
{
int u = q.front();
//cout << u <<endl;
q.pop();
if(u == t) return true;
for(int i = h[u]; i != -1; i = es[i].next)
{
int v = es[i].to;
if(!l[v] && es[i].c) {l[v] = l[u] + 1; q.push(v);}
}
}
return false;
}
int dfs(int x, int t, int mf)
{
if(x == t) return mf;
int ret = 0;
for(int &i = cur[x]; i != -1; i = es[i].next)
{
if(es[i].c && l[x] == l[es[i].to] - 1)
{
int f = dfs(es[i].to,t,min(es[i].c,mf - ret));
if(f) nxt[x] = es[i].to;
es[i].c -= f;
es[i^1].c += f;
ret += f;
if(ret == mf) return ret;
}
}
return ret;
}
int dinic(int s, int t)
{
int ans = 0;
while(bfs(s,t))
{
for(int i = 0; i <= t; i++) cur[i] = h[i];
ans += dfs(s,t,INF);
}
return ans;
}
int main()
{
scanf("%d%d",&n,&m);
tot = 0;
memset(nxt,-1,sizeof(nxt));
memset(h,-1,sizeof(h));
memset(vis,false,sizeof(vis));
int s = 0, t = 2*n+1,u,v;
for(int i = 1; i <= n; i++)
add_edge(s,i,1),add_edge(i+n,t,1);
for(int i = 0; i < m; i++)
{
scanf("%d%d",&u,&v);
add_edge(u,v+n,1);
}
int res = dinic(s,t);
for(int i = 1; i <= n; i++)
if(!vis[i])
{
vector <int> v;
int t = i;
do{
vis[t] = true;
v.push_back(t);
t = nxt[t]-n;
}while(t > 0);
for(int j = 0; j < v.size(); j++)
printf("%d%c",v[j], j == v.size() -1 ? '\n' : ' ');
}
printf("%d\n",n-res);
return 0;
}