• UVa10779 Collectors Problem 收集者的难题


    传送


    题面:Bob和他的朋友从糖果包装里收集贴纸。朋友每人手里都有一些(可能有重复的)贴纸,并且只跟别人交换他所没有的。总是一对一交换。Bob比这些朋友更聪明,因为他意识到只跟别人交换自己没有的贴纸并不总是最优的。在某些情况下,换来一张重复贴纸更划算。假设Bob的朋友只和Bob交换(他们之间不交换),并且这些朋友只会出让重复贴纸来交换没有的不同贴纸。帮Bob算出最终可以得到的不同贴纸的最大数量。


    这题现在我只是理解了建模的思路,但是原因没有想明白。


    首先我们建立源汇点(s,t),分别表示Bob能换出去和能收回来的贴纸数量。
    然后再建立(m)个点,表示每种贴纸。那(s)向每一种贴纸连边,容量是Bob拥有该糖纸的数量;每种贴纸向(t)连边,容量是1,这样就能求出种类数。
    这样在没有和其他人交换的情况下,我们的图就建立完了。


    如果考虑和人交换,那就应该把(m)个贴纸作为交换的媒介,一端是Bob,另一端是(n-1)个人。
    因为每个人只会交换重复的贴纸,所以如果第(i)个人有(a)个贴纸(j),那么就从(i)(j)连边,容量为(a-1),代表第(i)个人能换出去(a-1)个贴纸(j);否则若没有种类(j),就从(j)(i)连边,容量为(1),代表第(i)个人最多会接受一个贴纸(j)


    这样我们以(m)个贴纸作为中转,就建立了一个交换系统。而且会发现,一切的交换都是从源点,即Bob开始的:如果第(i)个人换出了一个贴纸,那么必然是有一条流从源点流到(i),再从(i)流向贴纸(j),即一定是Bob先把贴纸给他,他才会给出贴纸,正与题目契合。

    #include<cstdio>
    #include<iostream>
    #include<cmath>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<cctype>
    #include<vector>
    #include<queue>
    #include<assert.h>
    #include<ctime>
    using namespace std;
    #define enter puts("") 
    #define space putchar(' ')
    #define Mem(a, x) memset(a, x, sizeof(a))
    #define In inline
    #define forE(i, x, y) for(int i = head[x], y; ~i && (y = e[i].to); i = e[i].nxt)
    typedef long long ll;
    typedef double db;
    const int INF = 0x3f3f3f3f;
    const db eps = 1e-8;
    const int maxn = 40;
    const int maxm = 30;
    const int maxe = 1e3 + 5;
    In ll read()
    {
    	ll ans = 0;
    	char ch = getchar(), las = ' ';
    	while(!isdigit(ch)) las = ch, ch = getchar();
    	while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
    	if(las == '-') ans = -ans;
    	return ans;
    }
    In void write(ll x)
    {
    	if(x < 0) x = -x, putchar('-');
    	if(x >= 10) write(x / 10);
    	putchar(x % 10 + '0');
    }
    In void MYFILE()
    {
    #ifndef mrclr
    	freopen(".in", "r", stdin);
    	freopen(".out", "w", stdout);
    #endif
    }
    
    int n, m, s, t;
    struct Edge
    {
    	int nxt, to, cap, flow;
    }e[maxe];
    int head[maxn], ecnt = -1;
    In void addEdge(int x, int y, int w)
    {
    	e[++ecnt] = (Edge){head[x], y, w, 0};
    	head[x] = ecnt;
    	e[++ecnt] = (Edge){head[y], x, 0, 0};
    	head[y] = ecnt;
    }
    
    int num[maxm];
    In void buildGraph()
    {
    	s = 0, t = n + m;
    	int K = read(); Mem(num, 0);
    	for(int i = 1; i <= K; ++i) num[read()]++;
    	for(int i = 1; i <= m; ++i) addEdge(s, i, num[i]), addEdge(i, t, 1);
    	for(int i = 1; i < n; ++i)
    	{
    		K = read(); Mem(num, 0);
    		for(int j = 1; j <= K; ++j) num[read()]++;
    		for(int j = 1; j <= m; ++j)
    			if(num[j] > 1) addEdge(i + m, j, num[j] - 1);
    			else if(!num[j]) addEdge(j, i + m, 1);
    	}
    }
    
    int dis[maxn];
    In bool bfs()
    {
    	Mem(dis, 0), dis[s] = 1;
    	queue<int> q; q.push(s);
    	while(!q.empty())
    	{
    		int now = q.front(); q.pop();
    		for(int i = head[now], v; ~i; i = e[i].nxt)
    			if(e[i].cap > e[i].flow && !dis[v = e[i].to])
    				dis[v] = dis[now] + 1, q.push(v);
    	}
    	return dis[t];
    }
    int cur[maxn];
    In int dfs(int now, int res)
    {
    	if(now == t || res == 0) return res;
    	int flow = 0, f;
    	for(int& i = cur[now], v; ~i; i = e[i].nxt)
    	{
    		if(dis[v = e[i].to] == dis[now] + 1 && (f = dfs(v, min(res, e[i].cap - e[i].flow))) > 0)
    		{
    			e[i].flow += f, e[i ^ 1].flow -= f;
    			flow += f, res -= f;
    			if(res == 0) break;
    		}
    	}
    	return flow;
    }
    In int maxFlow()
    {
    	int flow = 0;
    	while(bfs())
    	{
    		memcpy(cur, head, sizeof(head));
    		flow += dfs(s, INF);
    	}
    	return flow;
    }
    int main()
    {
    //	MYFILE();
    	int T = read(), ID = 0;
    	while(T--)
    	{
    		Mem(head, -1), ecnt = -1;;
    		n = read(), m = read();
    		buildGraph();
    		printf("Case #%d: %d
    ", ++ID, maxFlow());
    	}
    	return 0;
    }
    
  • 相关阅读:
    jvisualvm工具使用
    Java四种引用包括强引用,软引用,弱引用,虚引用。
    <实战> 通过分析Heap Dump 来了解 Memory Leak ,Retained Heap,Shallow Heap
    什么是GC Roots
    Memory Analyzer tool(MAT)分析内存泄漏---理解Retained Heap、Shallow Heap、GC Root
    JDK自带工具之问题排查场景示例
    websocket协议握手详解
    ssh 登陆服务器原理
    新版本macos无法安装mysql-python包
    如何将多个小值存储进一个值中
  • 原文地址:https://www.cnblogs.com/mrclr/p/14901236.html
Copyright © 2020-2023  润新知