ZOJ 3642 最大流

题目很像是有上下界的,因为限定了每个小孩最少分享的信息。后来听YYD大神的解释是,也许一个人可以多次分享同一个,所以下界可以无视。如果是这样,题目就好办了。

首先源点向所有人连边,如果不是要求的那个人,边容量就设为他的上界,如果是要求的那个人,边容量就设为无穷,因为他的所有信息都不需要别人共享。

【或者也可以不连要求的那个人,连信息的时候,就同样不连那个人有的信息,最后最大流加上他已经有的信息】

人向自己有的信息连边,容量为1

信息连向汇点,容量为1.

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<vector>
#include<string>
#define eps  1e-12
#define INF   0x7fffffff
#define maxn 22222
using namespace std;
int n,m,c;
int en;
int st,ed;	//源点和汇点
int dis[maxn] ;//dis[i],表示  到 原点  s 的 层数
int que[100000];
struct edge
{
	int to,c,next;
};
edge e[100000];
int head[maxn];
void add(int a,int b,int c)
{
	e[en].to=b;
	e[en].c=c;
	e[en].next=head[a];
	head[a]=en++;
	e[en].to=a;
	e[en].c=0;
	e[en].next=head[b];
	head[b]=en++;
}
int bfs()
{
    memset(dis,-1,sizeof(dis));
    dis[st]=0;
    int front=0,rear=0;
    que[rear++]=st;
    while(front<rear)
    {
        int j=que[front++];
        for(int k=head[j];k!=-1;k=e[k].next)
        {
            int i=e[k].to;
			if(dis[i]==-1&&e[k].c)
            {
                dis[i] = dis[j]+ 1 ;
                que[rear++]=i;
                if(i==ed) return true;
            }
        }
    }
    return false;
}
int dfs(int x,int mx)
{
    int i,a;
    if(x==ed) return mx ;
int ret=0;
    for(int k=head[x];k!=-1&&ret<mx;k=e[k].next)
    {
        if(e[k].c&&dis[e[k].to]==dis[x]+1)
        {
            int dd=dfs(e[k].to,min(e[k].c,mx-ret));
            e[k].c-=dd;
            e[k^1].c+=dd;
            ret+=dd;
        }
    }
    if(!ret) dis[x]=-1;
    return ret;
}
void init()
{
    en=0;
	memset(head,-1,sizeof(head));
}
int x[1000];
int z[1000];
bool ok[1000];
void build()
{
    memset(ok,0,sizeof(ok));
    map<int,int> mp;
    vector<int> v[205];
    int y;
    int id=n+1;
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&x[i],&y,&z[i]);
        for(int j=1;j<=x[i];j++)
        {
            scanf("%d",&y);
            if(!mp[y]) mp[y]=id++;
            v[i].push_back(mp[y]);
        }
    }
    scanf("%d",&m);
    st=id++;
    ed=id++;
    for(int i=1;i<=n;i++)
    {
        if(i==m) add(st,i,INF);
        else add(st,i,z[i]);
        for(int j=0;j<v[i].size();j++)
        {
            add(i,v[i][j],1);
            if(!ok[v[i][j]])
            {
                add(v[i][j],ed,1);
                ok[v[i][j]]=1;
            }
        }
    }
}

int dinic()
{
    int tmp=0;
    int maxflow=0;
    while(bfs())
    {
        while(tmp=dfs(st,INF)) maxflow+=tmp;
    }
    return maxflow;
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        init();
        build();
        printf("%d\n",dinic());
    }
}

ZOJ 3642 最大流,布布扣,bubuko.com

时间: 2024-10-13 22:40:33

ZOJ 3642 最大流的相关文章

一道题看bitset应用 --ZOJ 3642

题意:给n个文件,包括文件名和文件大小,然后给出k个关键词,查询包含该关键词的文件的大小总和.文件名为一些中括号括起的关键词的合集. 解法:可用bitset记录每一个关键词在哪些文件中出现,然后查询即可. bitset用法如下: bitset<SIZE> bs; bool is_set = bs.any(); //是否存在1 bool not_set = bs.none(); //是否全0 int cnt_one = bs.count(); bs[index] = 1; bs.flip(ind

zoj 3642 Just Another Information Sharing Problem【最大流||多重匹配】

大意: 有n个熊孩子,,每个熊孩子有a个秘密,他最少愿意分享b个秘密, 最多愿意分享c个秘密, 接下来a个数表示这个熊孩子有的a个秘密的id 最后给一个熊孩子的编号m, 询问编号m最多能够知道多少个秘密 分析: 最大流, 但是询问的那个孩子的秘密就不用封印了,哈哈 也可以用二分图多重匹配, 而且时间快了一倍 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <

ZOJ 1698 (最大流入门)

Power NetworkTime Limit:5000MS    Memory Limit:32768KB    64bit IO Format:%lld & %llu SubmitStatusPracticeZOJ 1734 Appoint description: Description A power network consists of nodes (power stations, consumers and dispatchers) connected by power trans

zoj 3229 有源汇有上下界的最大流模板题

/*坑啊,pe的程序在zoj上原来是wa. 题目大意:一个屌丝给m个女神拍照.计划拍照n天,每一天屌丝最多个C个女神拍照,每天拍照数不能超过D张,并且给每一个女神i拍照有数量限制[Li,Ri], 对于每一个女神n天的拍照总和不能超过Gi,假设有解求屌丝最多能拍多少张照,并求每天给相应女神拍多少张照:否则输出-1. 解题思路:增设一源点st,汇点sd.st到第i天连一条上界为Di下界为0的边,每一个女神到汇点连一条下界为Gi上界为oo的边,对于每一天,当天到第i个女孩连一条[Li.Ri]的边. 建

ZOJ 2182 Cable TV Network(无向图点割-最大流)

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2182 题意:给出一个无向图,问最少删掉多少个顶点之后图变得不连通? 思路:将原图每个点拆点(i,i+n),连边<i,i+n,1>,对原图的边(u,v),连边<u+n,v,INF>,<v+n,u,INF>.然后对于每对顶点(i,j)跑最大流(i+n,j).所有最大流的最小值即为答案. struct node { int v,cap,nex

ZOJ 3229 有上下界最大流

1: /** 2: ZOJ 3229 有上下界的最大流 3: 两次求最大流的过程,非二分 4: 有源汇上下界的最大流问题, 首先连接 sink -> src, [0,INF]. 5: 根据net的正负,来建立 Supersrc 与 supersink 之间的边,做一次 maxflow. 6: 若所有的Supersrc 与 Supersink满流,则说明存在可行流. 7: 然后删除 sink -> src之间的边.(cap 置零即可). 从src -> sink 做一次最大流. 8: 两次

zoj 3231(上下界费用流)

题意:树上每个节点上有若干苹果,边上带权,问你最小费用使得书上的苹果方差最小. 思路:上下费用流问题,参考http://blog.csdn.net/qq564690377/article/details/8870587 代码如下: 1 /************************************************** 2 * Author : xiaohao Z 3 * Blog : http://www.cnblogs.com/shu-xiaohao/ 4 * Last m

ZOJ 3885 The Exchange of Items(费用流)

ZOJ 3885 The Exchange of Items Description Bob lives in an ancient village, where transactions are done by one item exchange with another. Bob is very clever and he knows what items will become more valuable later on. So, Bob has decided to do some b

ZOJ 3348 Schedule(map运用+网络流之最大流)(竞赛问题升级版)

题目地址:ZOJ 3348 仍然是一道竞赛问题的网络流问题,但是这道题再用上次的竞赛建图方法就不行了,5000场比赛,明显会超时,于是需要换种建图思路了.上一道经典竞赛问题戳这里 上一道的胜负转换是利用专门给比赛建一个点,通过对比赛双方的流向来控制胜负关系,这里的建图方法更加巧妙(膜拜想出这个方法的大牛...),是先假设其中一方获胜,用mp[a][b]来表示a赢b的次数,将a与b连边,权值为mp[a][b],这样的话,前面的假设就仅仅只是假设而已,因为在这里,如果a的流量流向了b,说明a的胜利果