题目大意:
有两台机器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;
}
本文探讨了如何通过合理分配任务到两台具有多种模式的机器上,并调整执行顺序来减少重启次数的问题。采用二分图的最大匹配算法求解最小顶点覆盖数,以实现最优调度。
8万+

被折叠的 条评论
为什么被折叠?



