最小路径覆盖。。。板子题。。。
之前用二分图搞了一下,这次用网络流写了一发
建图如下
s ----- i ---------------- i+n ------- t
容量设为 1
跑一边最大流就好了。。。。
以下是AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int maxn = 1e6+5;
const int INF = 0x3f3f3f3f;
struct node
{
int to;
int nxt;
int val;
}ed[maxn];
int head[maxn],tot;
int n,m;
bool vis[maxn];
int lin[maxn];
int pre[maxn];
void add(int u,int v,int w)
{
ed[++tot].to = v;
ed[tot].nxt = head[u];
ed[tot].val = w;
head[u] = tot;
ed[++tot].to = u;
ed[tot].nxt = head[v];
ed[tot].val = 0;
head[v] = tot;
}
void init()
{
memset(head,-1,sizeof head);
tot = -1;
}
int h[maxn];
bool bfs(int s,int t)
{
memset(h, 0, sizeof h);
h[s] = 1;
queue<int> q;
q.push(s);
while(q.size())
{
int u = q.front();
q.pop();
for(int i=head[u];~i;i=ed[i].nxt)
{
int v = ed[i].to;
if(h[v] == 0 && ed[i].val > 0)
{
h[v] = h[u] + 1;
q.push(v);
}
}
}
return h[t];
}
int dfs(int s,int t,int v)
{
if(s == t)
return v;
int add = 0;
for(int i=head[s];~i;i=ed[i].nxt)
{
int to = ed[i].to;
if(ed[i].val > 0 && h[to] == h[s] + 1)
{
int res = dfs(to, t, min(ed[i].val, v - add));
add += res;
ed[i].val -= res;
ed[i ^ 1].val += res;
if(res != 0 && s!=0 && to!=2*n+1)
{
lin[to - n] = s;
pre[s] = to - n;
}
}
}
if(add == 0)
h[s] = 0;
return add;
}
int dinic(int s,int t)
{
int ans = 0;
while(bfs(s,t))
{
ans += dfs(s,t,INF);
}
return ans;
}
int findd(int x)
{
if(pre[x]==x)
return x;
else
return pre[x]=findd(pre[x]);
}
void unite(int a,int b)
{
int fa=findd(a),fb=findd(b);
if(fa!=fb)
pre[fa]=fb;
}
int main()
{
int s,t;
scanf("%d%d",&n,&m);
init();
memset(vis,false,sizeof vis);
s = 0, t = 2*n + 1;
for(int i=1;i<=n;i++)
{
add(s,i,1);
add(i+n,t,1);
}
int u,v;
for(int i=1;i<=m;i++)
{
scanf("%d%d",&u,&v);
add(u,v+n,1);
}
int ans = dinic(s,t);
for(int i=1;i<=n;++i)
pre[i]=i;
for(int i=1;i<=n;++i)
{
for(int j=head[i];~j;j=ed[j].nxt)
{
if(!ed[j].val && ed[j].to - n <= n &&ed[j].to)
{
unite(i,ed[j].to-n);
}
}
}
for(int i=n;i;i--)
{
bool flag;
for(int j=1;j<=n;++j)
{
if(findd(j)==i)
{
printf("%d ",j);
flag=1;
}
}
if(flag)
printf("\n");
}
printf("%d\n",n - ans);
return 0;
}