转载了别人的分析
分析:显然,机器重启次数是两台机器需要使用的不同模式的个数。把每个任务看成一条边,即A机器的每个模式看成一个X节点,B机器的每个模式看成一个Y节点,任务i为边(ai, bi)。本题即求最少的点让每条边至少与其中的一点关联,即求一个点的最小覆盖。可以证明,这个最小覆盖就是该二分图的最大匹配数。故二分图匹配的模型就建好了。注意到开始时机器都处于0模式,所以如果某个任务可以在0模式下执行,则我们可以不考虑该任务,假定它已经被完成即可,也就是建图的时候不要把与0关联的边加到二分图中就可以得到正确的解。
来自:http://blog.csdn.net/hackbuteer1/article/details/7398008 写的很好留着以后能看
#include<iostream>
#include<cstdio>
#include<list>
#include<algorithm>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<cmath>
#include<memory.h>
#include<set>
#define ll long long
#define LL __int64
#define eps 1e-8
const ll INF=9999999999999;
using namespace std;
#define M 400000100
#define inf 0xfffffff
//vector<pair<int,int> > G;
//typedef pair<int,int> P;
//vector<pair<int,int>> ::iterator iter;
//
//map<ll,int>mp;
//map<ll,int>::iterator p;
vector<int>G[1212];
int mp[1212][1212];
int marry[1212];
bool vis[1212];
int dis[2][4]={0,-1,0,1,1,0,-1,0};
int n,m,k;
int cnt;
void clear()
{
cnt=0;
memset(marry,-1,sizeof(marry));
memset(mp,0,sizeof(mp));
for(int i=0;i<1012;i++)
G[i].clear();
}
bool dfs(int x)
{
for(int i=0;i<m;i++)
{
if(mp[x][i] && !vis[i])
{
vis[i]=true;
if(marry[i]==-1 || dfs(marry[i]))
{
marry[i]=x;
return 1;
}
}
}
return 0;
}
int main(void)
{
while(scanf("%d",&n),n)
{
cin>>m>>k;
clear();
int u,v,num;
for(int i=0;i<k;i++)
{
cin>>num>>u>>v;
if(u>0 && v>0)//注意到开始时机器都处于0模式,所以如果某个任务可以在0模式下执行,则我们可以不考虑该任务,
//假定它已经被完成即可,也就是建图的时候不要把与0关联的边加到二分图中就可以得到正确的解。
mp[u][v]=1;
}
int ans=0;
for(int i=0;i<n;i++)
{
memset(vis,false,sizeof(vis));
if(dfs(i))
ans++;
}
cout<<ans<<endl;
}
}