ZOJ2521 最小路径覆盖

来源:互联网 发布:淘宝助理违规校验错误 编辑:程序博客网 时间:2024/04/28 13:59

最小路径覆盖:就是最少的变把所有的顶点全部覆盖,意思是删除最少的边把全部的点删除
最小路径覆盖=总节点数-最大匹配数。
最小点覆盖:选择最少的点 把路径全部覆盖 意思就是删除最少的点 可以把边全部删除
二分图的最小点覆盖=最大匹配数

给定一个有向无环图,要用若干条不相交简单路径覆盖所有顶点,求最少的路径条数。

算法分析:
在有向无环图中,每条简单路径上有且仅有一个点没有后继。也就是说,每个没有后继的点就对应一条路径。要使路径条数最少,那么就是要没有后继的点的个数最少。
由于路径不相交,那么一个点最多有一个后继。转化一下,根据原图中的边建立二分图,左右各n个点。原图中有的边,就从左向右对应连边,代表它的所有可能后继。

那么问题就转化为最大二分匹配,匹配上的点就有后继,即可顺利解决。

#include<cstdio>#include<iostream>#include<cmath>#include<cstring>#include<vector>using namespace std;int flag[10][10];int val[1002];vector<int>vec[1002];int match[1002];int mate[1002];bool vis[1002];void Init(){    memset(flag,0,sizeof(flag));    flag[0][1]=flag[0][7]=true;    flag[3][1]=flag[3][7]=true;    flag[4][1]=true;    flag[6][5]=true;    flag[7][1]=true;    for(int i=0;i<=7;i++)flag[8][i]=true;      flag[9][1]=flag[9][3]=flag[9][4]=flag[9][5]=flag[9][7]=flag[8][9]=true;}bool Find(int cur){    int len=vec[cur].size();    for(int i=0;i<len;i++)    {         int t=vec[cur][i];        if(vis[t]) continue;        vis[t]=true;        if(match[t]==0||Find(match[t]))        {            match[t]=cur;            mate[cur]=t;            return true;        }        }    return false;}int main(){       int N;Init();    while(~scanf("%d",&N))    {        memset(match,0,sizeof(match));        memset(mate,0,sizeof(mate));        for(int i=1;i<=N;i++)        {            scanf("%d",&val[i]);            vec[i].clear();        }        for(int i=1;i<=N;i++)            for(int j=i+1;j<=N;j++)                   if(flag[val[i]][val[j]])                    vec[i].push_back(j);        int ans=0;        for(int i=1;i<=N;i++)            if(mate[i]==0)            {             memset(vis,0,sizeof(vis));             if(Find(i)) ans++;            }    printf("%d\n",N-ans);    }    return 0;}


原创粉丝点击