二分匹配问题 :最小覆盖=最大匹配
这道题要用匈牙利算法求最大匹配,机器A的所有模式为左部顶点,机器B的所有模式为右部顶点,然后A与B之间的每条连线代表一个任务或工作,问题是为什么最大匹配数就是机器要重启的次数。
我们可以这么想,因为要通过安排机器的顺序来使重启次数最少;所以跟机器的顺序就没什么关系了;所以A机器一定能被B机器替代;那么我们就只要找B的最小覆盖点就可以;
此题还要注意的一点是机器A、B启动时的模式都是0模式,所以若有在0模式可完成的任务就不能考虑在内,我们就可以从1开始遍历就好了。
#include<iostream> #include<cstdio> #include<cstdlib> #include<algorithm> #include<cmath> #include<queue> #include<set> #include<map> #include<cstring> #include<vector> using namespace std; bool G[124][124],visit[124]; int match[124]; bool path( int num , int N ) { for( int i = 1 ; i < N; i++ ) { if( !visit[i] && G[num][i] ) { visit[i] = 1; if( match[i] ==0 || path( match[i] ,N ) ) { match[i] = num; return true; } } } return false; } int main( ) { int n,m,k,num,a,b; while( scanf( "%d",&n ),n ) { memset( G , 0 , sizeof( G ) ); memset( match , 0 , sizeof( match ) ); scanf( "%d %d",&m,&k ); for( int i = 0; i < k ; i++ ) { scanf( "%d %d %d",&num , &a, &b ); G[a][b] = true; } int ans = 0; for( int i = 1 ; i < n ; i ++ ) { memset( visit , 0 , sizeof( visit ) ); if( path( i , m ) ) ans ++; } printf( "%d\n",ans ); } //system( "pause" ); return 0; }