POJ 1325:http://poj.org/problem?id=1325
题意:两台机器可以工作。各有n个和m个工作模式。皆标记为0、1、2、3、...... 、n(m)
给出k个任务,每个任务在两台机器上都可以完成,其分别在两台机器上完成需要对应的工作模式为(i,j)
表示在第一台机器上工作需要模式i,第二台机器上工作需要模式 j 。
机器初始为0工作状态。每一次改变工作状态需要重启。
求,完成所有工作最少重启几次。
画个图,左为左边机器的各个工作模式,右边为右边机器的各个工作模式。一个任务对应一条边。
很容易看出为——最小点覆盖。 选择最少的点覆盖所有边——选择最少的重启次数完成所有任务。
最少点覆盖数 = 最大匹配数。
WA了的主要原因是:
题目注明,起初两台机器的工作状态皆为0 。 所以含有0点的边都去掉,不需要考虑!!!!
然后模板。
#include"cstdio"
#include"cstring"
#include"vector"
#include"string"
#include"iostream"
#include"cstdlib"
using namespace std;
#define inf 109
#define loop(x,y,z) for(x=y;x<z;x++)
int n,m;
vector<int>edge[109];
int ans[inf],book[inf];
int sum;
void init()
{
int i;
sum=0;
loop(i,1,n)
edge[i].clear();
memset(ans,-1,sizeof ans);
}
int dfs(int v)
{
int i,len;
len=edge[v].size();
loop(i,0,len)
{
int u=edge[v][i];
if(!book[u])
{
book[u]=1;
if(ans[u]==-1||dfs(ans[u]))
{
ans[u]=v;
return 1;
}
}
}
return 0;
}
void XYL()
{
int i;
loop(i,1,n)
{
memset(book,0,sizeof book);
sum+=dfs(i);
}
}
int main()
{
int i,j,k,p;
while(~scanf("%d",&n)&&n)
{
scanf("%d%d",&m,&p);
init();
while(p--)
{
scanf("%d%d%d",&k,&i,&j);
if(i==0||j==0)continue;
edge[i].push_back(j);
}
XYL();
printf("%d\n",sum);
}
return 0;
}