03最小路径覆盖问题

可以用天津南开的oj提交,我开始案例都没过,一提交AC,因为是特判。题目链接http://acm.nankai.edu.cn/p2123.html

最小的路径条数=顶点数-最大匹配数。没一条路径就是一条增广路。

我们只需一路递归,只到节点的父亲为-1止,这便是一条路。

这题也可以建图,建立一个超级源点,超级汇点,边权为1.求最大流。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int N=151;
int um,vm,m,tot;
int xM[N],yM[N],vis[N],head[N];
struct node
{
    int v,next;
}e[N*N];
void add(int a,int b)
{
    e[tot].v=b;
    e[tot].next=head[a];
    head[a]=tot++;
}
bool find(int u)
{
    for(int i=head[u];i+1;i=e[i].next)
    {
        int v=e[i].v;
        if(!vis[v])
        {
            vis[v]=1;
            if(yM[v]==-1||find(yM[v]))//增广路
            {
                yM[v]=u;
                xM[u]=v;
                return true;
            }
        }
    }
    return false;
}
int max_match()
{
    int ret=0;
    memset(yM,-1,sizeof(yM));
    memset(xM,-1,sizeof(yM));
    for(int u=1;u<=um;u++)
    {
        if(xM[u]==-1)
        {
            memset(vis,0,sizeof(vis));
            if(find(u))
                ret++;
        }
    }
    return ret;
}
void dfs(int u)//输出路径
{
    vis[u]=1;
    if(xM[u]==-1)return ;
    u=xM[u];
    printf(" %d",u);
    dfs(u);
}
int main()
{
    int a,b,i;
    while(scanf("%d%d",&um,&m)!=EOF)
    {
        tot=0;
        memset(head,-1,sizeof(head));
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            add(a,b);
        }
        int ret=max_match();
        memset(vis,0,sizeof(vis));
        for(i=1;i<=um;i++)
        {
            if(!vis[i])
            {
                printf("%d",i);
                dfs(i);
                printf("\n");
            }
        }
        printf("%d\n",um-ret);
    }
    
    return 0;
}

 

posted on 2013-08-29 20:40  黎昊明  阅读(160)  评论(0编辑  收藏  举报

导航