算法设计与分析 6.2 路径覆盖

★题目描述

有向无环图上一条简单路径 V0->V1->. . .->Vl (V0可能等于Vl)覆盖了这条路径上的所有节点。

请找出一个简单路径的集合,使得每个节点恰好被覆盖一次,输出路径的最少条数。

★输入格式

输入的第一行两个数字n,m(1<=n<=100,1<=m<=n*(n-1)/2)$,表示有向无环图的节点数与边数。

接下来m行每行两个数字a,b(1<=a,b<=m)代表一条由a指向b的有向边。

★输出格式

输出一个整数表示最少需要的路径条数。

★样例输入

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

★样例输出

3

★提示

三条路径分别为(1->4->7->10->11),(2->5->8),(3->6->9)。

★参考代码

/*
也是一道二分图最大匹配的题

题目所问的最少的路径数 = 节点数n - 最大匹配数 
*/
#include
using namespace std;

int Match[101];
int Visit[101];

int H[101];
struct Edge{
    int end,nxt; //尾端点,头节点相同的下一条边 
}E[5000];

int idx=0;
void AddEdge(int u, int v){
    ++idx;
    E[idx].end=v, E[idx].nxt=H[u];
    H[u]=idx;
}

int find(int x){
    for(int i=H[x]; i!=0; i=E[i].nxt){
        int e=E[i].end;
        if(Visit[e]==0){
            Visit[e]=1;
            if(Match[e]==0 || find(Match[e])){
                Match[e]=x;
                return 1;
            }
        }
    }
    return 0;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    
    int n,m;
    cin>>n>>m;
    
    int u,v;
    while(m--){
        cin>>u>>v;
        AddEdge(u,v);
    } 
    
    int res=0;
    memset(Match, 0, sizeof(Match));
    for(int i=1; i<=n; ++i){
        memset(Visit, 0, sizeof(Visit));
        res += find(i);
    }
    
    cout<

你可能感兴趣的:(算法设计与分析 6.2 路径覆盖)