zoukankan      html  css  js  c++  java
  • JZOJ 1083. 【GDOI2006】拯救亚特兰蒂斯

    \(\text{Solution}\)

    自己的网络流技术太拉了
    连这样的题都做不出来
    对于一个怪物,剑术和法术两样东西有一样就可以了
    不难想到二分图中最小点覆盖,一条边只有两个端点之一被选就被覆盖了
    最小点覆盖等于最大匹配数

    \(\text{Code}\)

    #include <cstdio>
    #include <cstring>
    #include <map>
    #include <vector>
    #define RE register
    #define IN inline
    using namespace std;
    
    const int N = 11005, INF = 1e9;
    int p, n, m, S, T, tot, h[N], dep[N], cur[N], Q[N], bz[N];
    vector<int> g[N][2];
    map<string, int> mp;
    char s[20];
    struct edge{int to, nxt, w;}e[N * 10];
    IN void add(int x, int y, int w)
    {
    	e[++tot] = edge{y, h[x], w}, h[x] = tot;
    	e[++tot] = edge{x, h[y], 0}, h[y] = tot;
    }
    
    IN int bfs()
    {
    	for(RE int i = S; i <= T; i++) cur[i] = h[i], dep[i] = 0;
    	int head = 0, tail = 1; Q[1] = S, dep[S] = 1;
    	while (head < tail)
    	{
    		int now = Q[++head];
    		for(RE int i = h[now]; i; i = e[i].nxt)
    		{
    			int v = e[i].to;
    			if (dep[v] || !e[i].w) continue;
    			dep[v] = dep[now] + 1, Q[++tail] = v;
    		}
    	}
    	return dep[T];
    }
    int dfs(int x, int lim)
    {
    	if (x == T || lim <= 0) return lim;
    	int flow = 0;
    	for(RE int i = cur[x], v, f; i; i = e[i].nxt)
    	{
    		cur[x] = i, v = e[i].to;
    		if (dep[v] != dep[x] + 1 || !e[i].w) continue;
    		f = dfs(v, min(lim, e[i].w));
    		if (f <= 0) continue;
    		e[i].w -= f, e[i ^ 1].w += f, lim -= f, flow += f;
    		if (lim <= 0) break;
    	}
    	return flow;
    }
    IN void dinic()
    {
    	int flow = 0;
    	while (bfs()) flow += dfs(S, INF);
    	printf("%d\n", flow);
    }
    
    int main()
    {
    	scanf("%d%d%d", &p, &n, &m);
    	while (1)
    	{
    		if (n == -1 && m == -1 && p == -1) break;
    		T = 0, tot = 1, memset(h, 0, sizeof h); int cnt = 0;
    		for(RE int i = 1; i <= p; i++) g[i][0].clear(), g[i][1].clear(), bz[i] = 0;
    		
    		for(RE int i = 1; i <= p; i++) scanf("%s", s), mp[s] = ++cnt;
    		for(RE int i = 1, num, z; i <= n; i++)
    		{
    			scanf("%s%d", s, &num);
    			for(RE int j = 1; j <= num; j++) scanf("%s", s), g[z = mp[s]][0].push_back(i), bz[z] = 1;
    		}
    		for(RE int i = 1, num, z; i <= m; i++)
    		{
    			scanf("%s%d", s, &num), ++T;
    			for(RE int j = 1; j <= num; j++) scanf("%s", s), g[z = mp[s]][1].push_back(i + n), bz[z] = 1;
    		}
    		int flag = 0;
    		for(RE int i = 1; i <= p; i++) if (!bz[i]){flag = 1; printf("Poor Atlantis!\n"); break;};
    		if (!flag)
    		{
    			T = n + m + 1;
    			for(RE int i = 1; i <= n; i++) add(S, i, 1);
    			for(RE int i = 1; i <= m; i++) add(i + n, T, 1);
    			for(RE int i = 1; i <= p; i++)
    				for(RE int j = 0; j < g[i][0].size(); j++)
    					for(RE int k = 0; k < g[i][1].size(); k++) add(g[i][0][j], g[i][1][j], 1);
    			dinic();
    		}
    		scanf("%d%d%d", &p, &n, &m);
    	}
    }
    
  • 相关阅读:
    Java连接Elasticsearch
    使用EasyPoi导出Excel
    递归遍历组织机构树
    打算用mongodb mapreduce之前一定要知道的事!!!
    css 手机禁止页面拖动
    js各种验证代码
    async nodejs
    防止在iOS设备中的Safari将数字识别为电话号码
    SQL中char、varchar、nvarchar的区别
    双击事件阻止点击事件
  • 原文地址:https://www.cnblogs.com/leiyuanze/p/15823835.html
Copyright © 2011-2022 走看看