标签:
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 13977 | Accepted: 5973 |
Description
Input
Output
Sample Input
5 5 10 0 1 1 1 1 2 2 1 3 3 1 4 4 2 1 5 2 2 6 2 3 7 2 4 8 3 3 9 4 3 0
Sample Output
3
Source
题目大意就是有两台机器A,B,分别由m和n种模式,初始时都在模式0,现在有k个工作,每一个工作都可以将A设置成模式i或将B设置成模式j,但每一次更换模式时机器不得不要重启,求完成所有工作的最小重启次数
输入数据的第一行有三个数据,分别代表工作数,A/B的模式数,当输入0时结束程序,接下来多行,每行的开始代表工作的序号,和完成该工作需将A/B设置的模式数,
输出一个整数,代表机器最小重启次数,这一题关键的地方在于建图,图建好了问题就迎刃而解,这题可以将每一个工作的A/B的模式连接成一条边,这样就构成了一个二分图,这样每一个工作都可以由图中所构成的边完成,故我们只需要用最少的顶点覆盖每一条边就行了,也就是说题目要求求的最小重启次数实际上是要求二分图的最小覆盖数,在根据二分图的一个重要性质,最小覆盖数=最大匹配数;
#include<cstdio> #include<cstring> #include<iostream> using namespace std; #define N 201 int e[N][N],visx[N],visy[N],lkx[N],lky[N]; int n,m,k,ans; bool dfs(int u){ visx[u]=1; for(int i=1;i<=m;i++){ if(!visy[i]&&e[u][i]){ visy[i]=1; if(!lky[i]||dfs(lky[i])){ lkx[u]=i; lky[i]=u; return 1; } } } return 0; } int main(){ while(scanf("%d",&n)==1&&n){ ans=0; memset(e,0,sizeof e); memset(lkx,0,sizeof lkx); memset(lky,0,sizeof lky); scanf("%d%d",&m,&k); for(int i=1;i<=k;i++){ int p,x,y; scanf("%d%d%d",&p,&x,&y); e[x][y]=1; } for(int i=1;i<=n;i++){ if(!lkx[i]&&!visx[i]){ memset(visx,0,sizeof visx); memset(visy,0,sizeof visy); if(dfs(i)) ans++; } } printf("%d\n",ans); } return 0; }
标签:
原文地址:http://www.cnblogs.com/shenben/p/5633803.html