A公司和B公司有n个合作的子项目,每个子项目由A公司和B公司各一名员工参与。一名员工可以参与多个子项目。
一个员工如果担任了该项目的项目经理,它需要对所参与的该项目负责。一个员工也可以负责多个项目。
A公司和B公司需要保证所有子项目都能有人负责,问最少需要指定几名项目经理?
第一行为A公司的的人员id列表, 0< id数量 < 10000,用空格切分第二行为B公司的人员id列表, 0< id数量 < 10000,用空格切分第三行为有已经有多少个匹配数子项目合作关系n下面有n行,每一行为每个子项目的合作对应关系,为两个id,第一个为A公司的员工id,第二个为B公司的员工id,用空格区分
一个整数,A公司和B公司合起来至少需要指定几名项目经理
0 1 2 3 4 5 6 0 4 0 3 1 3 1 4 2 5 2 4
3
可行的一个保留人员方案是留下0,1,2即可,这样即可保证所有的子项目都有人cover到。
import java.util.Arrays; import java.util.Scanner; /** * 匈牙利算法 * 求二分图的最大匹配 */ public class Main { // 存放A员工匹配的B员工id static int[] match; // B员工是否已匹配 static boolean[] used; // A、B员工共同参与的项目,连线为1,不连线为0 static int[][] map; public static int solve(int[] companyA, int[] companyB) { Arrays.fill(match, -1); int res = 0; for (int i : companyA) { Arrays.fill(used, false); if (find(companyB, i)) { res++; } } return res; } public static boolean find(int[] companyB, int index) { for (int j : companyB) { if (map[index][j] == 1 && !used[j]) { used[j] = true; if (match[j] == -1 || find(companyB, match[j])) { match[j] = index; return true; } } } return false; } public static void main(String[] args) { Scanner s = new Scanner(System.in); String A = s.nextLine(); String B = s.nextLine(); String[] sa = A.split(" "); String[] sb = B.split(" "); int[] companyA = new int[sa.length]; int[] companyB = new int[sb.length]; int a = 0, b = 0; int maxa = 0, maxb = 0; for (String str : sa){ int c = Integer.parseInt(str); companyA[a++] = c; maxa = Math.max(maxa, c); } for (String str : sb){ int c = Integer.parseInt(str); companyB[b++] = c; maxb = Math.max(maxb, c); } match = new int[maxb+1]; used = new boolean[maxb+1]; map = new int[maxa+1][maxb+1]; int n = s.nextInt(); while (n-- > 0) { int fir = s.nextInt(); int sec = s.nextInt(); map[fir][sec] = 1; } System.out.println(solve(companyA, companyB)); s.close(); } }
if __name__ == '__main__': def dfs(x, graph_dict, visited, left): b_members = graph_dict[x] for b_m in b_members: # 同一次 增广路寻找中,若v曾经被达到过,则跳过。 if visited[b_m] == 0: # 若x能到达的 右部结点 b_m 为非匹配点,则找到了一条长度为1的增广路,记:left[b_m] = x visited[b_m] = 1 if b_m not in left.keys(): left[b_m] = x return True else: # 若 b_m 为匹配点,则递归的从left[b_m]出发寻找增广路,回溯时记:left[b_m] = x dfs(left[b_m], graph_dict, visited, left) left[b_m] = x return True return False # a_company = list(map(int, input().split(' '))) # b_company = list(map(int, input().split(' '))) # n = int(input()) # projects = [] # for _ in range(n): # temp = list(map(int, input().split(' '))) # projects.append(temp) a_company = [0, 1, 2] b_company = [3, 4, 5] projects = [[0, 4], [0, 3], [1, 3], [1, 4], [2, 5], [2, 4]] graph_dict = {} for p in projects: if p[0] not in graph_dict.keys(): graph_dict[p[0]] = [] graph_dict[p[0]].append(p[1]) # 根据建立的二分图,寻找 最大匹配数 = 最小点覆盖数 visited = {} # 记录右部节点是否被匹配过 for b_m in b_company: visited[b_m] = 0 left = {} # 匹配右部i点的左部节点 ans = 0 for a_m in a_company: # 从a公司的任一节点出发,依次寻找增广路,并查找返回结果 if dfs(a_m, graph_dict, visited, left): ans += 1 print(ans)
import collections a = list(map(int, input().split())) b = list(map(int, input().split())) n = int(input()) tmp1 = collections.defaultdict(list) tmp2 = collections.defaultdict(list) tmp3 = collections.defaultdict(set) for i in range(n): x, y = list(map(int, input().split())) tmp3[x].add(y) m = 20000 st = [False] * m match = [-1] * m def find(x, tmp): #print(x,match) for i in tmp[x]: #print(i) if st[i] == False: st[i] = True if (match[i] == -1 or find(match[i], tmp)): match[i] = x return True return False res = 0 for i in a: if (find(i, tmp3)): st = [False] * m res += 1; #print(match,a) print(res)
二分图:一个二分图中的最大匹配数等于这个图中的最小点覆盖数
注意:
/** 匈牙利算法 */ import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.*; public class Main { static int n, idx, N = 20010, M = 2 * N; static int[] h = new int[N], e = new int[M], ne = new int[M]; static int[] v1 = new int[N], v2 = new int[N]; static int[] match = new int[N]; static boolean[] st = new boolean[N]; static int res = 0; static void add(int a, int b){ e[idx] = b; ne[idx] = h[a]; h[a] = idx ++; } public static void main(String[] args) throws IOException { BufferedReader bf = new BufferedReader(new InputStreamReader(System.in)); String[] arr = bf.readLine().split(" "); String[] brr = bf.readLine().split(" "); for(int i = 1; i <= arr.length; i ++ ){ v1[i] = Integer.parseInt(arr[i - 1]); } for(int i = 1; i <= brr.length; i ++){ v2[i] = Integer.parseInt(brr[i - 1]); } n = Integer.parseInt(bf.readLine()); Arrays.fill(h, -1); for(int i = 1; i <= n; i ++){ String[] crr = bf.readLine().split(" "); int a = Integer.parseInt(crr[0]), b = Integer.parseInt(crr[1]); add(a, b); add(b, a); } for(int i = 1; i <= arr.length; i ++){ int u = v1[i]; Arrays.fill(st, false); if(find(u)) res ++; } System.out.println(res); } static boolean find(int u){ for(int i = h[u]; i != -1; i = ne[i]){ int j = e[i]; if(st[j]) continue; st[j] = true; if(match[j] == 0 || find(match[j])){ match[j] = u; return true; } } return false; } }
public class Main { static Map<Integer,List<Integer>> map; static int[] p; static boolean[] vis; static int l,r; public static void main(String[] args) { Scanner in = new Scanner(System.in); in.nextLine().split(" "); in.nextLine().split(" "); int n = in.nextInt(); map = new HashMap<>(); for(int i = 0;i < n;i++){ int idA = in.nextInt(); int idB = in.nextInt(); List<Integer> list = map.get(idA); if(list == null){ list = new ArrayList<>(); map.put(idA,list); } list.add(idB); } vis = new boolean[10001]; p = new int[10001]; int result = 0; for(Integer id : map.keySet()){ Arrays.fill(vis,false); if(match(id)){ result++; } } System.out.print(result); } public static boolean match(int id){ List<Integer> list = map.get(id); for(Integer idB : list){ if(!vis[idB]){ vis[idB] = true; if(p[idB] == 0 || match(p[idB])){ p[idB] = id; return true; } } } return false; } }
import java.util.*; public class Main { // 邻接矩阵 public static Map<Integer, List<Integer>> map = new HashMap<>(); public static boolean[] vis = new boolean[10010]; public static int[] match = new int[10010]; public static void main(String[] args) { Scanner sc = new Scanner(System.in); // 初始化第一个数组 String[] tmp = sc.nextLine().split(" "); int n = tmp.length; int[] v1 = new int[n]; for (int i = 0; i < n; i++) { v1[i] = Integer.parseInt(tmp[i]); map.put(v1[i], new ArrayList<>()); } // 初始化第二个数组 String[] tmp1 = sc.nextLine().split(" "); int m = tmp1.length; int[] v2 = new int[m]; for (int i = 0; i < m; i++) { v2[i] = Integer.parseInt(tmp1[i]); } // 构建领接矩阵 int k = sc.nextInt(); while (k-- > 0) { int x = sc.nextInt(); int y = sc.nextInt(); map.get(x).add(y); } // 匈牙利算法 int res = 0; for (int i = 0; i < n; i++) { int num = v1[i]; Arrays.fill(vis, false); if (find(num)) res++; } System.out.println(res); } // 匈牙利算法 public static boolean find(int x) { // 得到边 List<Integer> list = map.get(x); for (int i = 0; i < list.size(); i++) { int y = list.get(i); // 没有访问过 if (vis[y]) continue; vis[y] = true; // 名花无主 或者能腾一个位置出来 if (match[y] == 0 || find(match[y])) { match[y] = x; return true; } } return false; } }
#include<bits/stdc++.h> using namespace std; vector<int> get(string s, int diff) { vector<int> a; stringstream str(s); int temp; while (str >> temp) a.push_back(temp + diff); return a; } const int maxn = 20100; vector<vector<int>> e; int match[maxn]; bool vis[maxn]; int ans; bool dfs(int u) { for (int v:e[u]) { if (!vis[v]) { vis[v] = true; if (match[v] == -1 || dfs(match[v])) { match[v] = u; match[u] = v; return true; } } } return false; } int main() { vector<int> a, b; string s; getline(cin, s); a = get(s, 0); getline(cin, s); b = get(s, 0); int n; cin >> n; e = vector<vector<int>>(maxn); for (int i = 0; i < n; i++) { int u, v; cin >> u >> v; // v+=10000; e[u].push_back(v); e[v].push_back(u); } ans = 0; memset(vis, 0, sizeof(vis)); memset(match, -1, sizeof(match)); for (int i = 0; i < a.size(); i++) { if (match[a[i]] == -1) { memset(vis, 0, sizeof(vis)); if (dfs(a[i])) ans++; } } cout << ans << endl; }
def readToInt(): return [int(n) for n in input().split()] companyA = readToInt() companyB = readToInt() pairs = [] for _ in range(int(input())): pairs.append(readToInt()) count = float("inf") def dfs(index, selected): global count if index >= len(pairs): count = min(count, len(selected)) return if len(selected) >= count: return pair = pairs[index] if pair[0] in selected&nbs***bsp;pair[1] in selected: dfs(index + 1, selected) else: selected.add(pair[0]) dfs(index + 1, selected) selected.remove(pair[0]) selected.add(pair[1]) dfs(index + 1, selected) selected.remove(pair[1]) dfs(0, set()) print(count)