Collectors Problem

https://vjudge.net/problem/UVA-10779#author=0

网络流

1.Bob向他有的贴纸连边,流量为他有的贴纸数量

2.每一种贴纸向汇点连流量为1的边

3.其余人,如果没贴纸i,由i向这个人连一条流量为1的边

4.如果贴纸i数量>1,由这个人向i连一条流量为数量-1的边

#include <cstdio>
#include <algorithm>
#include <queue>

using namespace std;
const int N = 45;
const int M = 650;

#define gc getchar()
#define oo 999999999

int n, m, now, S, T, TI;
int head[N], now_head[N], calc[N], dis[N];
struct Node{
    int u, v, flow, nxt;
}G[M];
queue <int> Q;

inline int read(){
    int x = 0; char c = gc;
    while(c < ‘0‘ || c > ‘9‘) c = gc;
    while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = gc;
    return x;
}

inline void add(int u, int v, int flow){
    G[now].v = v; G[now].flow = flow; G[now].nxt = head[u]; head[u] = now ++;
}

inline bool bfs(){
    for(int i = S; i <= T; i ++) now_head[i] = head[i], dis[i] = -1;
    dis[S] = 0;
    while(!Q.empty()) Q.pop();
    Q.push(S);
    while(!Q.empty()){
        int topp = Q.front();
        Q.pop();
        for(int i = head[topp]; ~ i; i = G[i].nxt){
            int v = G[i].v;
            if(dis[v] == -1 && G[i].flow > 0){
                dis[v] = dis[topp] + 1;
                if(v == T) return 1;
                Q.push(v);
            }
        }
    }
    return 0;
}

int dfs(int now, int flow){
    if(now == T) return flow;
    int ret = 0;
    for(int & i = now_head[now]; ~ i; i = G[i].nxt){
        int v = G[i].v;
        if(dis[v] == dis[now] + 1 && G[i].flow > 0){
            int f = dfs(v, min(G[i].flow, flow - ret));
            if(f) {G[i].flow -= f; G[i ^ 1].flow += f; ret += f; if(ret == flow) break;}
        }
    }
    if(ret != flow) dis[now] = -1;
    return ret;
}

inline int Dinic(){
    int ret = 0;
    while(bfs()) ret += dfs(S, oo);
    return ret;
}

int main()
{
    TI = read();
    for(int Ti = 1; Ti <= TI; Ti ++){
        n = read(); m = read(); now = 0;
        T = n + m + 1; S = 1;
        for(int i = 0; i <= T; i ++) head[i] = -1;
        for(int i = 1; i <= m; i ++) add(n + i, T, 1), add(T, n + i, 0);
        int k = read();
        for(int i = 1; i <= k; i ++){int im = read(); calc[im] ++;}
        for(int i = 1; i <= m; i ++) if(calc[i]) add(1, n + i, calc[i]), add(n + i, 1, 0);
        for(int i = 1; i <= m; i ++) calc[i] = 0;
        for(int i = 2; i <= n; i ++){
            int k = read();
            for(int j = 1; j <= k; j ++){int im = read(); calc[im] ++;}
            for(int j = 1; j <= m; j ++)
                if(calc[j] > 1) add(i, n + j, calc[j] - 1), add(n + j, i, 0);
                else if(!calc[j]) add(n + j, i, 1), add(i, n + j, 0);
            for(int j = 1; j <= m; j ++) calc[j] = 0;
        }
        int answer = Dinic();
        printf("Case #%d: %d\n", Ti, answer);
    }

    return 0;
}
/*
2
2 5
6 1 1 1 1 1 1
3 1 2 2
3 5
4 1 2 1 1
3 2 2 2
5 1 3 4 4 3
*/
时间: 2024-09-30 18:00:30

Collectors Problem的相关文章

UVA 10779 - Collectors Problem(网络流)

UVA 10779 - Collectors Problem 题目链接 题意:每个人有一种贴图,现在第0个人要去和别人交换贴图,来保证自己的贴图尽量多,只有别人没有该种贴图,并且自己有2张以上另一种贴图才会换,问最多有几张贴图 思路:最大流,关键在于如何建模,把0号人和物品连边,容量为有的容量,然后其他人如果物品等于0的,连一条边从物品到这个人,表示能交换,然后如果物品大于1的,连一条边从这个人到物品,容量为物品减1(自己要留一个),然后把所有物品连到汇点,跑一次最大流即可 代码: #inclu

UVa10779 Collectors Problem(最大流)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=33631 [思路] 最大流. 构图: 1  建立m个x点表示贴纸,n-1个y点表示Bob的朋友,ST表示源汇点. 2  S向x[j]连一条容量为sum[0][j]的边,表示Bob可以换出如是贴纸. 3  y[j]向x[i]连容量为1的边当且仅当i没有j,x[i]向y[j]连容量为sum[i][j]-1的边.  4  x[i]向T连一条容量为1的边统计不同种类的数目.

UVA 10779 Collectors Problem[最大流]

from:neopenx 题目大意:Bob有一些贴纸,他可以和别人交换,他可以把自己独有的贴纸拿出去,也可以把重复的贴纸拿出去(有时候把独有的贴纸而不是重复的贴纸拿出去能换到更多贴纸). Bob的朋友也有一些贴纸,但是他们只会拿自己重复的贴纸和Bob换,而且换的是自己没有的贴纸. 求Bob最后最多能有多少种贴纸. 解题思路: 题目意思很明确了.就算把重复的贴纸拿出去也不一定最优,贪心就不用尝试了. 全局资源调配得使用网络流模型. 建图方式: ①S点(看作是Bob)->所有物品:连一条边,cap是

UVA 10779 Collectors Problem 网络流+建图

题目链接:点击打开链接 题意:白书P370 思路: 因为问的是最后贴纸总数,那么就设最后的贴纸总数是网络流的答案. 首先我们模拟贴纸的流动过程: Bob 的 某种贴纸a -> 给一个没有a贴纸的人Peo -> 还给Bob一个Peo的某张重复贴纸 -> 这张贴纸可以算作答案了 #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include

uva 10779 Collectors Problem

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

UVA-10779 Collectors Problem (网络流建模)

题目大意:有n个人,已知每人有ki个糖纸,并且知道每张糖纸的颜色.其中,Bob希望能和同伴交换使得手上的糖纸数尽量多.他的同伴只会用手上的重复的交换手上没有的,并且他的同伴们之间不会产生交换.求出Bob能拥有的最大糖纸种数. 题目分析:对于Bob拥有的糖纸,从源点s连一条弧,容量为Bob拥有的数量:对于Bob的小伙伴,从Bob连一条弧向他拥有的糖纸,容量为拥有数量减1,对于他不拥有的糖纸,连一条有向弧从糖纸到他,容量为1:对于每一种糖纸,连一条弧向汇点t.最大流便是答案. 代码如下: # inc

cs224d problem set2 (三) 用RNNLM模型实现Language Model,来预测下一个单词的出现

今天将的还是cs224d 的problem set2 的第三部分习题, 原来国外大学的系统难度真的如此之大,相比之下还是默默地再天朝继续搬砖吧 (注意前方高能,一大批天书即将来袭) ''' Created on 2017年9月26日 @author: weizhen ''' import getpass import sys import time import numpy as np from copy import deepcopy from utils import calculate_p

A Math Problem

A Math Problem Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 237    Accepted Submission(s): 117 Problem Description You are given a positive integer n, please count how many positive integers

Water Problem

water problem 发布时间: 2015年10月10日 15:34   时间限制: 1000ms   内存限制: 256M 描述 题意很简单 给你N个数, Q个查询 每次查询给你一个区间[L, R] 你要找出 [L, R] 这个区间里面取模M后的最大值. 输入 第一行一个T,表示测试数据组数.第二行两个整数N, M (1<=N<=10^5, 1<=M<=10^9).第三行给你N个整数 整数范围在1到10^9之间.第四行给你一个整数Q. ( 1<=Q<=10^5)