POJ1325机器重启次数——二分图匈牙利算法模板

题目:http://poj.org/problem?id=1325

求最小点覆盖。输出最大匹配数就行,结果略复杂地弄了。

注意由题可知 可以直接把与0有关的边删掉。不过亲测不删0而计数时不计0就会WA。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int n,m,k,pre[205],head[205],xnt,a,x,y,ans;
bool vis[205];
struct Node{
    int next,to;
}edge[2005];
void add(int x,int y)
{
    edge[++xnt].next=head[x];
    edge[xnt].to=y;
    head[x]=xnt;
}
bool dfs(int u)
{
    vis[u]=1;
    for(int i=head[u];i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(vis[v])continue;
        vis[v]=1;
        if(!pre[v]||dfs(pre[v]))
        {
            pre[v]=u;pre[u]=v;return true;
        }
    }
    return false;
}
int main()
{
    while(1)
    {
        scanf("%d",&n);
        if(!n)return 0;
        memset(pre,0,sizeof pre);
        memset(head,0,sizeof head);
        xnt=0;ans=0;
        scanf("%d%d",&m,&k);
        for(int i=1;i<=k;i++)
        {
            scanf("%d%d%d",&a,&x,&y);
            if(!x||!y)continue;
            add(x,y+100);add(y+100,x);
        }
        for(int i=1;i<n;i++)
            if(!pre[i])
            {
                memset(vis,0,sizeof vis);
                vis[i]=1;dfs(i);
            }
        memset(vis,0,sizeof vis);
        for(int i=1;i<n;i++)
            if(!pre[i])
            {
                vis[i]=1;dfs(i);
            }
        for(int i=1;i<n;i++)
            if(!vis[i])ans++;
        for(int i=101;i<m+100;i++)
            if(vis[i])ans++;
        printf("%d\n",ans);
    }
}

 

posted on 2018-02-23 22:08  Narh  阅读(92)  评论(0编辑  收藏

导航