376. 机器任务(最小点覆盖)

376. 机器任务

最小点覆盖==最大匹配.

最小点的覆盖由于所有的边,所以对于每一个边来说,两边的点至少要选一个..

这就是最小点覆盖的2性质...

针对于这道题我们思考对于每个任务,要求a[i],b[i]至少要有一个模式,所以我们就将a的模式放一边,b的模式放一半,对于每一个任务连边

最后做最大匹配.

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=110,M=1010;
int n,m,match[N],vis[N],link[N],tot,id,k;
struct edge{int y,next;}a[M];
inline int read()
{
    int x=0,ff=1;
    char ch=getchar();
    while(!isdigit(ch)) {if(ch=='-') ff=-1;ch=getchar();}
    while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    return x*ff;
}
inline void add(int x,int y)
{
    a[++tot].y=y;
    a[tot].next=link[x];
    link[x]=tot;
}
inline bool dfs(int x)
{
    for(int i=link[x];i;i=a[i].next)
    {
        int y=a[i].y;
        if(vis[y]!=id)
        {
            vis[y]=id;
            if(!match[y]||dfs(match[y])) {match[y]=x;return true;}
        }
    }
    return false;
}
int main()
{
    //freopen("1.in","r",stdin);
    while(n=read())
    {
        memset(a,0,sizeof(a));tot=0;
        memset(link,0,sizeof(link));
        memset(match,0,sizeof(match));
        m=read();k=read();
        for(int i=1;i<=k;++i)
        {
            int id=read(),x=read(),y=read();
            if(x==0||y==0) continue;
            add(x,y);
        }
        int ans=0;
        for(int i=1;i<=n;++i)
        {
            ++id;
            if(dfs(i)) ans++;
        }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

 

posted @ 2020-03-09 16:13  逆天峰  阅读(198)  评论(0编辑  收藏  举报
作者:逆天峰
出处:https://www.cnblogs.com/gcfer//