Problem Description
As we all know, machine scheduling is a very classical problem in computer science and has been studied for a very long history. Scheduling problems differ widely in the nature of the constraints that must be satisfied and the type of schedule desired. Here we consider a 2-machine scheduling problem.(问题描述;众所周知,机器调度是计算机科学中一个非常经典的问题,已经研究了很长时间。调度问题在必须满足的约束的性质和期望的调度类型上有很大的不同。这里我们考虑一个两机器调度问题。)
There are two machines A and B. Machine A has n kinds of working modes, which is called mode_0, mode_1, …, mode_n-1, likewise machine B has m kinds of working modes, mode_0, mode_1, … , mode_m-1. At the beginning they are both work at mode_0.(机器A和B两种,机器A有n种工作模式,分别叫mode_0,mode_1,…,mode_n-1,同样机器B有m种工作模式,mode_0,mode_1,…,mode_m-1。开始时,它们都在模式0下工作。)
For k jobs given, each of them can be processed in either one of the two machines in particular mode. For example, job 0 can either be processed in machine A at mode_3 or in machine B at mode_4, job 1 can either be processed in machine A at mode_2 or in machine B at mode_4, and so on. Thus, for job i, the constraint can be represent as a triple (i, x, y), which means it can be processed either in machine A at mode_x, or in machine B at mode_y.(对于给定的k个作业,它们中的每一个都可以在两台机器中的任何一台上以特定的模式进行处理。例如,作业0可以在模式3下在机器A中处理,也可以在模式4下在机器B中处理,作业1可以在模式2下在机器A中处理,也可以在模式4下在机器B中处理,以此类推。因此,对于作业I,约束可以表示为三重(I,x,y),这意味着它可以在模式x下在机器A中处理,或者在模式y下在机器B中处理。)
Obviously, to accomplish all the jobs, we need to change the machine’s working mode from time to time, but unfortunately, the machine’s working mode can only be changed by restarting it manually. By changing the sequence of the jobs and assigning each job to a suitable machine, please write a program to minimize the times of restarting machines.(显然,为了完成所有的工作,我们需要不时地改变机器的工作模式,但不幸的是,机器的工作模式只能通过手动重新启动来改变。通过改变作业的顺序并将每个作业分配给合适的机器,请编写一个程序来最大限度地减少重新启动机器的时间。)
Input
The input file for this program consists of several configurations. The first line of one configuration contains three positive integers: n, m (n, m < 100) and k (k < 1000). The following k lines give the constrains of the k jobs, each line is a triple: i, x, y.(输入这个程序的输入文件由几个配置组成。一个配置的第一行包含三个正整数:n,m (n,m < 100)和k (k < 1000)。下面的k行给出了k个作业的约束,每一行是一个三元组:I,x,y。)
The input will be terminated by a line containing a single zero.(输入将被一个包含单个零的行终止)
Output
The output should be one integer per line, which means the minimal times of restarting machine.(输入将被一个包含单个零的行终止)
机器的每一个状态用一个点表示,是一个二分图,如果在每个任务指定的两个状态连一条线的话就可以用一条边代表这个任务,而让这个任务在某台机器上执行就是给这条边选择一个端点,每切换一次状态就是选择一个点,如此转化为了:求最少的顶点,使边集中的每一条边都与某个顶点关联,即求二分图的最小点覆盖
二分图的最小点覆盖数=最大匹配数
#include <iostream>
#include "cstring"
bool map[111][111],use[111]; // use为标记过的点集。
int path[111],n,m; //定义数组,n,m为数组的两个部分。
using namespace std;
int find(int u){
for(int i = 1; i <= m; i++) // 从n的u开始出发寻找,遍历m中的每一个点。
{
if(map [u][i] && ! use[i] )
{
use[i] = 1; // 如果 u i 之间有边,但是 i 还没有被访问,则记录下此点。
if(path[i] == -1 || find(path[i])) //若此点有匹配对象点,寻找从此点对应的匹配点出发的其他路径。
{
path[i] = u; // 更换对象继续寻找。
return 1;
}
}
}
return 0;
}
int main(){
int a,b,k;
while (cin >> n&&n)
{
cin >> m >> n;
memset(map, false, sizeof(map)); // 将 map 中的全部值设为 false。
memset(path, -1, sizeof(path)); // 将 path 中的全部值设为 -1。
for(int i = 0;i <= m; i ++)
{
cin >> a >> b;
map[a][b] = true; // 从 m 中的 i开始寻找并且标记。
}
int sum = 0;
for(int i = 1; i <= n; i ++)
{
memset(use, 0, sizeof(use)); // 将use中的点设为0.
if(find(i))
sum ++; // 设置最初始的匹配数为0,从 n 中的i开始寻找,找到匹配数加一。
}
cout << sum << endl ;
}
return 0;
}
memset函数是按一个字节一个字节来给数组或者是结构体赋值的,
给字符数组复制时可以赋任意值,详见:百度百科memse函数点击打开链接
但需要注意的是给int型的数组复制时的几点注意:
一般常用的复制方式有:
int a[MAXN];
memset(a, 0, sizeof(a)); //数组中的所有元素全为0
memset(a, -1, sizeof(a)); //数组中的所有元素全为-1
memset(a, 127, sizeof(a)); //数组中的所有元素全为2139062143(可以将其视为INF)
C++中的find函数
在非string类型的容器里,可以直接找出所对应的元素.find函数需要几个参数:迭代器,下标值,所要找的元素。
vector<int> a;
find(a.begin(),a.end(),1);
这句话就表示从a的头开始一直到尾,找到第一个值为1的元素,返回的是一个指向该元素的迭代器。