zoukankan      html  css  js  c++  java
  • YbtOJ大收藏家【分层图,最大流】

    正题

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


    题目大意

    \(n\)个人,每人有\(a_i\)个属于自己的物品。\(m\)次交换依次进行,每次\(x_i,y_i\)两个人可以决定拿不拿自己的一个物品进行交换。

    \(1\)号人最后能拿到最多多少种物品

    \(1\leq n,m,a_i\leq 3000\)


    解题思路

    每种物品只需要一个,所以每种物品的第一个可以视为流量,\(a_i\)可以视为自己的物品处的空位(自己的物品可以不视为自己的)。

    \(x_i,y_i\)的交换可以视为一条流量为\(1\)的双向边,因为依次进行所以要分成\(m\)层,然后每一层有交换的连边。

    发现这样有很多点没有用到,去掉这些多余的,那点数就是\(O(n+m)\)级别的了

    跑最大流就好了


    code

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int N=12100,inf=1e9;
    struct node{
    	int to,next,w;
    }a[N<<2];
    int T,n,m,tot,cnt,ans,s,t;
    int ls[N],dep[N],p[N],w[N];
    queue<int> q;
    void addl(int x,int y,int w){
    	a[++tot].to=y;a[tot].next=ls[x];ls[x]=tot;a[tot].w=w;
    	a[++tot].to=x;a[tot].next=ls[y];ls[y]=tot;a[tot].w=0;
    	return;
    }
    bool bfs(){
    	memset(dep,0,sizeof(dep));dep[s]=1;
    	while(!q.empty())q.pop();q.push(s);
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		for(int i=ls[x];i;i=a[i].next){
    			int y=a[i].to;
    			if(dep[y]||!a[i].w)continue;
    			dep[y]=dep[x]+1;
    			if(y==t)return 1;
    			q.push(y);
    		} 
    	}
    	return 0;
    }
    int dinic(int x,int flow){
    	if(x==t)return flow;
    	int rest=0,k;
    	for(int i=ls[x];i;i=a[i].next){
    		int y=a[i].to;
    		if(dep[x]+1!=dep[y]||!a[i].w)continue;
    		rest+=(k=dinic(y,min(a[i].w,flow-rest)));
    		a[i].w-=k;a[i^1].w+=k;
    		if(rest==flow)return rest;
    	}
    	if(!rest)dep[x]=0;
    	return rest;
    }
    int main()
    {
    	freopen("collection.in","r",stdin);
    	freopen("collection.out","w",stdout);
    	scanf("%d",&T);
    	while(T--){
    		tot=0;memset(ls,0,sizeof(ls));
    		scanf("%d%d",&n,&m);
    		s=tot=1;t=cnt=2;ans=0;
    		for(int i=1;i<=n;i++){
    			p[i]=++cnt;
    			scanf("%d",&w[i]);
    			addl(s,p[i],1);
    		}
    		for(int i=1;i<=m;i++){
    			int x,y;scanf("%d%d",&x,&y);
    			++cnt;addl(p[x],cnt,w[x]);p[x]=cnt;
    			++cnt;addl(p[y],cnt,w[y]);p[y]=cnt;
    			addl(p[x],p[y],1);addl(p[y],p[x],1);
    		}
    		addl(p[1],t,inf);
    		while(bfs())
    			ans+=dinic(s,inf);
    		printf("%d\n",ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    父子进程 signal 出现 Interrupted system call 问题
    一个测试文章
    《淘宝客户端 for Android》项目实战 html webkit android css3
    Django 中的 ForeignKey ContentType GenericForeignKey 对应的数据库结构
    coreseek 出现段错误和Unigram dictionary load Error 新情况(Gentoo)
    一个 PAM dbus 例子
    漫画统计学 T分数
    解决 paramiko 安装问题 Unable to find vcvarsall.bat
    20141202
    js
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14412567.html
Copyright © 2011-2022 走看看