zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Selenium简单测试页面加载速度的性能(Page loading performance)
    Selenium Page object Pattern usage
    Selenium如何支持测试Windows application
    UI Automation的两个成熟的框架(QTP 和Selenium)
    分享自己针对Automation做的两个成熟的框架(QTP 和Selenium)
    敏捷开发中的测试金字塔(转)
    Selenium 的基础框架类
    selenium2 run in Jenkins GUI testing not visible or browser not open but run in background浏览器后台运行不可见
    eclipse与SVN 结合(删除SVN中已经上传的问题)
    配置Jenkins的slave节点的详细步骤适合windows等其他平台
  • 原文地址:https://www.cnblogs.com/mrclr/p/14901236.html
Copyright © 2011-2022 走看看