zoukankan      html  css  js  c++  java
  • day20T3改错记

    题目描述

    两个点集(A)(B),有(m)条边,每条边连接(A)中的一个点和(B)中的一个点

    每个点有属性(t)(只能是(0)或者(1)),若(a in A, b in B, t_a = t_b),且(a, b)之间有边,则(a)(b)可以匹配

    (A)中每个点的(t)已知,(B)中每个点的(t)未知,问在所有可能的情况下,(A)(B)的最大匹配的最小是多少

    (|A|, |B| le 2000, m le 5000)

    解析

    奇妙的网络流建图……

    (A)中的点分为(t)(0)(t)(1)分成两部分(A_0, A_1)(S)(A_0)中每个点连容量为(1)的边,(A_1)中每个点向(T)连容量为(1)的边

    (B)中每个点拆成(b_0, b_1)两个点,(b_0)(b_1)连一条容量为(1)的边

    (A_0)中每个点向能匹配的(b_0)连容量(inf)的边,每个(b_1)(A_1)中能匹配的点连容量(inf)的边

    跑一遍最小割就是答案

    其实依然不太清楚为什么这么连边……

    代码

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    #define MAXN 2005
    
    typedef long long LL;
    const int inf = 0x3f3f3f3f;
    struct Graph {
    	struct Edge {
    		int v, next, cap;
    		Edge(int _v = 0, int _n = 0, int _c = 0):v(_v), next(_n), cap(_c) {}
    	} edge[MAXN << 4];
    	int head[MAXN << 2], cur[MAXN << 2], dep[MAXN << 2], cnt;
    	void init() { memset(head, -1, sizeof head); cnt = 0; }
    	void add_edge(int u, int v, int c) { edge[cnt] = Edge(v, head[u], c); head[u] = cnt++; }
    	void insert(int u, int v, int c) { add_edge(u, v, c); add_edge(v, u, 0); }
    	bool bfs();
    	int dfs(int, int);
    	int dinic();
    };
    
    char gc();
    int read();
    
    int N, M, K, t[MAXN];
    Graph G;
    
    int main() {
    	freopen("deadline.in", "r", stdin);
    	freopen("deadline.out", "w", stdout);
    
    	N = read(), M = read(), K = read();
    	G.init();
    	for (int i = 1; i <= N; ++i) {
    		t[i] = read();
    		if (t[i]) G.insert(i, N + (M << 1) + 1, 1);
    		else G.insert(0, i, 1);
    	}
    	while (K--) {
    		int x = read(), y = read();
    		if (t[x]) G.insert(N + M + y, x, inf);
    		else G.insert(x, N + y, inf);
    	}
    	for (int i = 1; i <= M; ++i) G.insert(N + i, N + M + i, 1);
    	printf("%d
    ", G.dinic());
    
    	return 0;
    }
    inline char gc() {
    	static char buf[1000000], *p1, *p2;
    	if (p1 == p2) p1 = (p2 = buf) + fread(buf, 1, 1000000, stdin);
    	return p1 == p2 ? EOF : *p2++;
    }
    inline int read() {
    	int res = 0; char ch = gc();
    	while (ch < '0' || ch > '9') ch = gc();
    	while (ch >= '0' && ch <= '9') res = (res << 1) + (res << 3) + ch - '0', ch = gc();
    	return res;
    }
    bool Graph::bfs() {
    	memset(dep, 0, sizeof dep);
    	int que[MAXN << 2], hd = 0, tl = 0;
    	que[tl++] = 0, dep[0] = 1;
    	while (hd < tl) {
    		int p = que[hd++];
    		if (p == N + (M << 1) + 1) return 1;
    		for (int i = head[p]; ~i; i = edge[i].next)
    			if (edge[i].cap && !dep[edge[i].v]) {
    				dep[edge[i].v] = dep[p] + 1;
    				que[tl++] = edge[i].v;
    			}
    	}
    	return 0;
    }
    int Graph::dfs(int u, int max_flow) {
    	if (u == N + (M << 1) + 1) return max_flow;
    	int res = 0;
    	for (int &i = cur[u]; ~i; i = edge[i].next)
    		if (edge[i].cap && dep[edge[i].v] == dep[u] + 1) {
    			int d = dfs(edge[i].v, std::min(max_flow, edge[i].cap));
    			if (d) {
    				res += d, max_flow -= d;
    				edge[i].cap -= d, edge[i ^ 1].cap += d;
    				if (!max_flow) break;
    			}
    		}
    	if (!res) dep[u] = -1;
    	return res;
    }
    int Graph::dinic() {
    	int res = 0;
    	while (bfs()) {
    		memcpy(cur, head, sizeof head);
    		res += dfs(0, inf);
    	}
    	return res;
    }
    //Rhein_E 100pts
    
  • 相关阅读:
    phpHttp请求头
    第八周学习总结
    梦断代码阅读笔记-03
    第七周学习总结
    针对自己开发项目的NABC的认知
    梦断代码阅读笔记
    第六周学习总结
    第五周学习总结
    移动端疫情展示
    第四周学习总结
  • 原文地址:https://www.cnblogs.com/Rhein-E/p/10585142.html
Copyright © 2011-2022 走看看