版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zimengxueying/article/details/78975772
杭电oj 1150
题目大意:有两台机器A和B以及N个需要运行的任务。每台机器有M种不同的模式,而每个任务都恰好在一台机器上运行。如果它在机器A上运行,则机器A需要设置为模式xi,如果它在机器B上运行,则机器A需要设置为模式yi。每台机器上的任务可以按照任意顺序执行,但是每台机器每转换一次模式需要重启一次。请合理为每个任务安排一台机器并合理安排顺序,使得机器重启次数尽量少。
二分图的最小顶点覆盖数=最大匹配数
从百度百科上找的匈牙利算法,其中需要复习的地方还是很多啊,有关图论的相关概念,已经如何从题目中找出二分图的算法。
以下是代码:
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#define ms(a,b) memset(a,b,sizeof(a))
using namespace std;
#define N 110
//用到了匈牙利算法
/*
需要结合图论的有关知识
要知道增广路的含义
以及要知道如何从实际问题中抽象出算法
这一点还需要自己慢慢来
*/
int m,n;//二部图两边的顶点个数
int G[N][N];// 两顶点是否连通
int used[N];//用来检测点有没有被访问过
int result[N]; //记录下顶点增广路径的值
#include<cmath>
#include<iostream>
#include<algorithm>
#define ms(a,b) memset(a,b,sizeof(a))
using namespace std;
#define N 110
//用到了匈牙利算法
/*
需要结合图论的有关知识
要知道增广路的含义
以及要知道如何从实际问题中抽象出算法
这一点还需要自己慢慢来
*/
int m,n;//二部图两边的顶点个数
int G[N][N];// 两顶点是否连通
int used[N];//用来检测点有没有被访问过
int result[N]; //记录下顶点增广路径的值
int dfs(int v)
{
int i;
for(i=0;i<m;i++){ //遍历右边的点
if(!used[i]&&G[v][i]==1)
{
used[1]=1;
if(result[i]==0||dfs(result[i]))
{
//这里还需要仔细的看一下,理解递归,以及增光路的含义
result[i]=v;
return 1;
}
}
}
return 0;
}
int solve()
{
int ans=0;
int i;
ms(result,-1);
for(i=0;i<n;i++){
ms(used,0);
if(dfs(i)!=0){
ans++;
}
}
return ans;
}
int main()
{
int k;
int j,i,l,r;
int ans;
while(scanf("%d",&n))
{
if(n==0) break;
scanf("%d%d",&m,&k);
ms(G,0);
for(j=0;j<k;j++){
scanf("%d%d%d",&i,&l,&r);
if(l>0&&r>0){
G[l][r]=1;
}
}
ans=solve();
printf("%d\n",ans);
}
return 0;
}
{
int i;
for(i=0;i<m;i++){ //遍历右边的点
if(!used[i]&&G[v][i]==1)
{
used[1]=1;
if(result[i]==0||dfs(result[i]))
{
//这里还需要仔细的看一下,理解递归,以及增光路的含义
result[i]=v;
return 1;
}
}
}
return 0;
}
int solve()
{
int ans=0;
int i;
ms(result,-1);
for(i=0;i<n;i++){
ms(used,0);
if(dfs(i)!=0){
ans++;
}
}
return ans;
}
int main()
{
int k;
int j,i,l,r;
int ans;
while(scanf("%d",&n))
{
if(n==0) break;
scanf("%d%d",&m,&k);
ms(G,0);
for(j=0;j<k;j++){
scanf("%d%d%d",&i,&l,&r);
if(l>0&&r>0){
G[l][r]=1;
}
}
ans=solve();
printf("%d\n",ans);
}
return 0;
}