LOJ6002最小路径覆盖(网络流24题)

题目描述
给定有向图 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连
对于边 ( x , y ) ( x 1 , y 2 )
跑最大匹配
减一下就行了

#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;
} 

猜你喜欢

转载自blog.csdn.net/a1035719430/article/details/81290567