这个题我想了一上午没都想的思路,刚开始按照自己的思维进行探索,结果一个小小的例子就被否定了!无奈之下还是去看了解题报告……
原来它是一个:求最小覆盖点数。额,本来对这个概念并不是太熟悉,接触更多的是最大匹配~
解题思想:本来这个题给人的情形是MachineA——Jobs——MachineB,根本想不到可以转换成MachineA——MachineB即转化为求最小覆盖点数,而最小覆盖点数==最大匹配数,即求最大匹配数即可!具体的说A——B,把边作为jobs,而任意一边都可以用A或者B的某一种模式完成,所以每一条边,都可以连着A_i,B_j(i,j表示模式i,j),则试着选取最少的A_i和B_j即选择最少的模式,那么它就是求最小覆盖点数(求覆盖所有边的最少点数)需要注意的是0模式是初始模式,不需要重启,所以能用0模式工作的不要去练即0不连线
View Code
#include <stdio.h>
#include <string.h>
#define N 102
#define M 1002
int nodev[N];
int nodeu[M],next[M];
void Build_Graph(int m)
{
int i,v,u,vain,ind;
memset(nodev,-1,sizeof(nodev)); ind=0;
for(i=0;i<m;i++)
{
scanf("%d %d %d",&vain,&v,&u);
if(v && u)
{
nodeu[ind]=u;
next[ind]=nodev[v];
nodev[v]=ind;
ind++;
}
}
}
int pre[N];
bool no[N];
bool find(int v)
{
int i,u;
for(i=nodev[v];i!=-1;i=next[i])
{
u=nodeu[i];
if(!no[u])
{
if(pre[u]==-1 || ( no[u]=true,find(pre[u]) ) )
{
pre[u]=v;
return true;
}
}
}
return false;
}
int solve(int n)
{
int v,ans=0;
memset(pre,-1,sizeof(pre));
for(v=1;v<=n;v++)
{
memset(no,false,sizeof(no));
if(find(v)) ans++;
}
return ans;
}
int main()
{
int n,num,m;
// freopen("input.txt","r",stdin);
while(scanf("%d",&n) && n)
{
scanf("%d %d",&num,&m);
Build_Graph(m);
printf("%d\n",solve(n));
}
return 0;
}