zoukankan      html  css  js  c++  java
  • 【YbtOJ#582】大收藏家

    题目

    题目链接:https://www.ybtoj.com.cn/contest/117/problem/2

    (Tleq 10,n,m,a_ileq 3000)

    思路

    我们只需要最大化 (1) 最终藏品数量,那么显然所有人的藏品可以看作只有一个黑色,剩余 (a_i-1) 个全部都是没有用的白色。我们需要最大化最后 (1) 号黑色的藏品数量。
    考虑如果两个人交换两个黑色的,那么其实等价于没有交换。如果交换两个白色的,那么毫无意义。所以我们肯定只让一个黑色和一个白色进行交换。
    所以我们可以把白色看作是格子,也就是任何人任何时刻的物品不能超过 (a_i) 个,每一次的“交换”其实可以看做一个人把自己的物品给另一个人。
    这很符合一个网络流模型。把所有人拆成 (m+1) 个点,从源点向所有人第一个点连一条流量为一的边。对于第 (i) 个时刻,每一个人的第 (i) 个点向第 (i+1) 个点连一条流量为 (a_i) 的边,限制最多只能有 (a_i) 个物品。如果 (x)(y) 在第 (i) 时刻交换物品,那么就在 (x,y) 的第 (i) 号点之间连一条流量为 (1) 的双向边。最后 (1) 的第 (m+1) 个点向汇点连边。
    但是这样点数是 (O(nm)) 的,不可接受。我们发现每一个时刻只需要连这个时刻有关的人的点就可以了。这样点数就降到了 (O(n+m))
    时间复杂度 (O(Tnm))

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N=10010,Inf=1e9;
    int Q,S,T,n,m,maxf,tot,a[N],U[N],V[N],head[N],last[N],dep[N],cur[N];
    
    struct edge
    {
    	int next,to,flow;
    }e[N*10];
    
    void add(int from,int to,int flow)
    {
    	e[++tot]=(edge){head[from],to,flow};
    	head[from]=tot;
    	swap(from,to);
    	e[++tot]=(edge){head[from],to,0};
    	head[from]=tot;
    }
    
    bool bfs()
    {
    	memset(dep,0x3f3f3f3f,sizeof(dep));
    	memcpy(cur,head,sizeof(cur));
    	queue<int> q;
    	q.push(S); dep[S]=0;
    	while (q.size())
    	{
    		int u=q.front(); q.pop();
    		for (int i=head[u];~i;i=e[i].next)
    		{
    			int v=e[i].to;
    			if (e[i].flow && dep[v]>dep[u]+1)
    			{
    				dep[v]=dep[u]+1;
    				q.push(v);
    			}
    		}
    	}
    	return dep[T]<Inf;
    }
    
    int dfs(int x,int flow)
    {
    	if (x==T) return flow;
    	int used=0,res;
    	for (int i=cur[x];~i;i=e[i].next)
    	{
    		int v=e[i].to; cur[x]=i;
    		if (e[i].flow && dep[v]==dep[x]+1)
    		{
    			res=dfs(v,min(e[i].flow,flow-used));
    			used+=res;
    			e[i].flow-=res; e[i^1].flow+=res;
    			if (flow==used) return used;
    		}
    	}
    	return used;
    }
    
    void dinic()
    {
    	while (bfs()) maxf+=dfs(S,Inf);
    }
    
    int main()
    {
    	freopen("collection.in","r",stdin);
    	freopen("collection.out","w",stdout);
    	S=N-1; T=N-2;
    	scanf("%d",&Q);
    	while (Q--)
    	{
    		memset(head,-1,sizeof(head));
    		tot=1; maxf=0;
    		scanf("%d%d",&n,&m);
    		for (int i=1;i<=n;i++)
    		{
    			scanf("%d",&a[i]);
    			last[i]=i; add(S,i,1);
    		}
    		for (int i=1;i<=m;i++)
    		{
    			scanf("%d%d",&U[i],&V[i]);
    			add(last[U[i]],n+i*2-1,a[U[i]]);
    			add(last[V[i]],n+i*2,a[V[i]]);
    			add(n+i*2-1,n+i*2,1);
    			add(n+i*2,n+i*2-1,1);
    			last[U[i]]=n+i*2-1; last[V[i]]=n+i*2;
    		}
    		add(last[1],T,a[1]);
    		dinic();
    		printf("%d
    ",maxf);
    	}
    	return 0;
    }
    
  • 相关阅读:
    每日总结2021.9.14
    jar包下载mvn
    每日总结EL表达语言 JSTL标签
    每日学习总结之数据中台概述
    Server Tomcat v9.0 Server at localhost failed to start
    Server Tomcat v9.0 Server at localhost failed to start(2)
    链表 java
    MVC 中用JS跳转窗体Window.Location.href
    Oracle 关键字
    MVC 配置路由 反复走控制其中的action (int?)
  • 原文地址:https://www.cnblogs.com/stoorz/p/14412034.html
Copyright © 2011-2022 走看看