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; }