题目描述
给定有向图 G=(V,E)。设 P 是 G 的一个简单路(顶点不相交)的集合。如果 V V V 中每个顶点恰好在 P P P 的一条路上,则称 P P P 是 G G G 的一个路径覆盖。P P P 中路径可以从 V V V 的任何一个顶点开始,长度也是任意的,特别地,可以为 0 0 0。G G G 的最小路径覆盖是 G G G 的所含路径条数最少的路径覆盖。
设计一个有效算法求一个有向无环图 G G G 的最小路径覆盖。
输入格式
第 1 1 1 行有 2 2 2 个正整数 n n n 和 m m m。n n n 是给定有向无环图 G G G 的顶点数,m m m 是 G G G 的边数。
接下来的 m m m 行,每行有 2 2 2 个正整数 u u u 和 v v v,表示一条有向边 (i,j) (i, j) (i,j)。
输出格式
从第 1 1 1 行开始,每行输出一条路径。
文件的最后一行是最少路径数。
样例
样例输入
11 12
1 2
1 3
1 4
2 5
3 6
4 7
5 8
6 9
7 10
8 11
9 11
10 11
样例输出
1 4 7 10 11
2 5 8
3 6 9
3
数据范围与提示
1≤n≤200,1≤m≤6000 1 \leq n \leq 200, 1 \leq m \leq 6000 1≤n≤200,1≤m≤6000
最小路径覆盖。
拆点,S向x1连,x2向T连
对于边
连
跑最大匹配
减一下就行了
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int ans;
int n , m , S , T;
int linkk[1100] , t , dep[1100];
bool flag;
bool vis[1100];
const int oo = 0x7fffffff;
struct node{
int n , y , v;
}e[1001000];
int read()
{
int sum = 0;char c = getchar();bool flag = true;
while( c < '0' || c > '9' ) {if(c == '-') flag = false;c = getchar();}
while( c >= '0' && c <= '9' ) sum = sum * 10 + c - 48 , c = getchar();
if(flag) return sum;
else return -sum;
}
void insert(int x,int y,int z)
{
e[++t].y = y;e[t].n = linkk[x];e[t].v = z;linkk[x] = t;
e[++t].y = x;e[t].n = linkk[y];e[t].v = 0;linkk[y] = t;
}
void init()
{
t = 1;
n = read();m = read();S = 2 * n + 1;T = 2 * n + 2;
for(int i = 1;i <= m;++i)
{
int x = read() , y = read() + n;
insert(x , y , 1);
}
for(int i = 1;i <= n;++i) insert(S , i , 1) , insert(i + n , T , 1);
return;
}
ll dfs(int x,ll lazy)
{
if(x == T) return lazy;
ll nowlazy = 0;
ll d = 0;
for(int i = linkk[x];i&&nowlazy < lazy;i = e[i].n)
{
int y = e[i].y;
if(dep[y] == dep[x] + 1 && e[i].v > 0)
if(d = dfs(y,min(1ll*e[i].v , lazy - nowlazy)))
{
nowlazy += d;
e[i].v -= d;
e[i^1].v += d;
}
}
if(nowlazy == 0) dep[x] = -1;
return nowlazy;
}
queue<int>q;
bool bfs()
{
memset(dep,-1,sizeof(dep));
dep[S] = 0;q.push(S);
while(q.size())
{
int v = q.front();
for(int i = linkk[v];i;i = e[i].n)
if(dep[e[i].y] == -1 && e[i].v > 0)
dep[e[i].y] = dep[v] + 1,q.push(e[i].y);
q.pop();
}
if(dep[T] == -1) return false;
return true;
}
int main()
{
init();
while(bfs())
{
ll d;
while(d = dfs(S,oo)) ans += d;
}
ans = n - ans;
for(int i = 1;i <= n;++i)
if(!vis[i])
{
int x = i + n;
while(1)
{
x -= n;
vis[x] = true;
printf("%d ",x);
bool flag = false;
for(int i = linkk[x];i;i = e[i].n)
if(e[i].y != S && e[i].v == 0)
{
flag = true;
x = e[i].y;
break;
}
if(!flag) break;
}
printf("\n");
}
printf("%lld\n",ans);
return 0;
}