题目大意:
有两台机器A和B以及N个需要运行的任务。每台机器有M种不同的模式,而每个任务都恰好在一台机器上运行。
如果它在机器A上运行,则机器A需要设置为模式xi,如果它在机器B上运行,则机器A需要设置为模式yi。
每台机器上的任务可以按照任意顺序执行,但是每台机器每转换一次模式需要重启一次。请合理为每个任务安排一台机器并合理安排顺序,使得机器重启次数尽量少。
在二分图中求最少的点,让每条边都至少和其中的一个点关联,这就是:“二分图的最小顶点覆盖”求最少的点,让每条边都至少和其中的一个点关联,这就是
二分图的最小顶点覆盖数=最大匹配数
本题就是求最小顶点覆盖数的。
#include <stdio.h> #include <string.h> #include <stdlib.h> #define max(a, b) (((a) > (b)) ? (a) : (b)) #define min(a, b) (((a) < (b)) ? (a) : (b)) #define FALSE 0 #define TRUE 1 #define infinity 0x0f0f0f0f #define minus_inf 0x80808080 #define MAXSIZE 109 typedef struct tagNODE { int mode[100] ; } ; int n, m, k, cnt ; int job, m1, m2 ; int cover[MAXSIZE], link[MAXSIZE] ; int adj[MAXSIZE][MAXSIZE] ; int find (int i) { int j ; for (j = 1 ; j < m ; ++j) { // j 在本次查找中没有被覆盖过, 且i 能与j 连通 if (cover[j] == FALSE && adj[i][j] == TRUE) { cover[j] = TRUE ; if (link[j] == FALSE || find (link[j]) == TRUE) { link[j] = i ; return 1 ; } } } return 0 ; } int main () { int i, j ; while (scanf ("%d", &n), n) { memset (adj, FALSE, sizeof (adj)) ; scanf ("%d%d", &m, &k) ; for (i = 0 ; i < k ; ++i) { scanf ("%d%d%d", &job, &m1, &m2) ; adj[m1][m2] = 1 ; } cnt = 0 ; memset (link, FALSE, sizeof (link)) ; // i 不用从0 开始,因为0 是初始状态,即是说, // 所有用0 状态解决的工作都不算入"重启次数"中, // 因为这些工作根本不需要重启机器 for (i = 1 ; i < n ; ++i) { memset (cover, FALSE, sizeof (cover)) ; if (find(i) == TRUE) ++cnt ; } printf ("%d\n", cnt) ; } return 0 ; }c++版本
#include <string> #include <vector> #include <iostream> using namespace std; bool mark1[100],mark2[100]; int list[100]; int n,m,edge,num; vector<vector<int> > v; bool dfs(int to) { int i ,point ,s = list[to]; for(i=0;i<v[s].size();i++) { point=v[s][i]; if(!mark2[point]) continue; mark2[point] = false; if(list[point] == -1 || dfs(point)) { list[point] = s; return true; } } return false; } void solve() { int i,j,point; bool flag=false; memset(mark1,true,sizeof(mark1)); memset(list,-1,sizeof(list)); num=0; for(i=0;i<n;i++) { for(j = 0; j < v[i].size();j++) { if(list[v[i][j]] == -1) { mark1[i] = false; list[v[i][j]] = i; num++; if(i==0) flag=true; break; } } } for(i=0;i<n;i++) { if(mark1[i]) { if(!v[i].empty()) { memset(mark2,true,sizeof(mark2)); for(j=0;j<v[i].size();j++) { point = v[i][j]; if(!mark2[point]) continue; mark2[point] = false; if(list[point] == -1 || dfs(point)) { list[point] = i; num++; break; } } } mark1[i] =false; } } if(flag || list[0]!=-1) cout<<num-1<<endl; else cout<<num<<endl; } int main() { int i,j,s,d; while(cin>>n) { if(n==0) break; v.clear(); v.resize(n); cin>>m>>edge; for(i=0;i<edge;i++) { cin>>j>>s>>d; v[s].push_back(d); } solve(); } return 0; }