zoukankan      html  css  js  c++  java
  • UVA1194 Machine Schedule[二分图最小点覆盖]

    题意翻译

    有两台机器 A,B 分别有 n,m 种模式。

    现在有 k 个任务。对于每个任务 i ,给定两个整数$ a_i(和) b_i$,表示如果该任务在 A上执行,需要设置模式为 (a_i);如果该任务在 B** 上执行,需要设置模式为$ b_i$。

    每台机器第一次开机默认处在0模式,且第一次开机不需要消耗时间。任务可以以任意顺序被执行,但每台机器转换一次模式就要重启一次。求怎样分配任务并合理安排顺序,能使机器重启次数最少。

    1 leq n,m leq 1001≤n,m≤100,1 leq k leq 10001≤k≤1000,1 leq a_i leq n1≤a**in,1 leq b_i leq m1≤b**im

    可能有多组数据。

    解析

    二分图最小点覆盖。

    容易看出,这就是一张二分图,A、B的不同模式分别是左部和右部的点。

    我们要解决的问题是,对于任意一个任务,我们可以把它看作一条边。对于这条边,我们必须要选择二分图中任意一部的点,即最小点覆盖。

    定理

    二分图最小点覆盖包含点数=二分图最大匹配数

    根据这个定理,我们用匈牙利求最大匹配就行。

    参考代码

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<cstring>
    #include<ctime>
    #include<cstdlib>
    #include<algorithm>
    #include<queue>
    #include<set>
    #include<map>
    #include<bitset>
    #define N 1010
    using namespace std;
    int n,m,k,f[N];
    vector<int> g[N];
    bitset<N> v;
    inline bool dfs(int x)
    {
    	for(int i=0;i<g[x].size();++i){
    		int y=g[x][i];
    		if(v[y]) continue;
    		v[y]=1;
    		if(!f[y]||dfs(f[y])){
    			f[y]=x;
    			return 1;
    		}
    	}
    	return 0;
    }
    int main()
    {
    	while(~scanf("%d",&n)&&n!=0){
    		for(int i=1;i<=n;++i) g[i].clear();
    		v.reset();memset(f,0,sizeof(f));
    		scanf("%d%d",&m,&k);
    		while(k--){		
    			int num,u,v;
    			scanf("%d%d%d",&num,&u,&v);
    			g[u].push_back(v+n),g[v+n].push_back(u);
    		}
    		getchar();
    		int ans=0;
    		for(int i=1;i<=n;++i){
    			v.reset();ans+=dfs(i);
    		}
    		cout<<ans<<endl;
    	}
    	return 0;
    }
    
  • 相关阅读:
    脚本——1-100的和
    脚本——删除文件为0大小的文件
    脚本——ping网址
    脚本——大于5k的文件有
    脚本——九九乘法表
    第十天:小数与随机数
    第九天:单元测试
    第八天:错误异常处理
    第七天(1):包与模块管理
    第七天(2):面向对象编程
  • 原文地址:https://www.cnblogs.com/DarkValkyrie/p/11371924.html
Copyright © 2011-2022 走看看