二分图 最小路径覆盖

定义:在一个有向图中,找出最少的路径,使得这些路径,经过每一个点,且每一个点只与一条路径相关联,

由上面得出:

1.一个单独的点是一个路径

2:如果有路径a,b,c。。。。f,g。a为起点,g为终点。那么a到g的点不在与其他点之间存在有向边。

最小路径覆盖=点数---最大匹配数

证明:
1  如果匹配数为0,那么图中没有边,需要n条路径

2  如果a,b之间连一条边,那么匹配数增1,需要的路径数会减少一,因为a,b之间只需要一条,那么就证明了

**********************一个最好的利用是 把点分为i与i’点,建立二分图

模板。

 

View Code
#include<iostream>

#include<string.h>

#include<stdio.h>

#include<algorithm>

#include<vector>

#define maxn 10000

using namespace std;

vector<int>node[maxn];

int mm[maxn];

int visit[maxn];

int n,m;

void init()

{

    cin>>n>>m;//输入点数,边数

    for(int i=0;i<=n;i++)

    node[i].clear();

    for(int i=0;i<m;i++)

    {

        int a,b;

        cin>>a>>b;

        node[a].push_back(b);//建边

    }

}

int dfs(int fa)

{

    for(int i=0;i<node[fa].size();i++)

    {

        int v=node[fa][i];

        if(!visit[v])

        {

            visit[v]=1;

            if(mm[v]==-1||dfs(mm[v]))

            {

                mm[v]=fa;

                return 1;

            }

        }

    }

    return 0;

}

void solve()

{

    int cnt=0;

    memset(mm,-1,sizeof(mm));

    for(int i=1;i<=n;i++)

    {

        memset(visit,0,sizeof(visit));

        if(dfs(i))cnt++;

    }

    cout<<n-cnt<<endl;//最小路径覆盖=点数-最大匹配数

}

int main()

{

    int test;

    cin>>test;

    while(test--)

    {

        init();

        solve();

    }

    return 0;

}

你可能感兴趣的:(二分图)