zoukankan      html  css  js  c++  java
  • PA2014 Muzeum

    如果不考虑复杂度,显然可以最大权闭合子图。
    考虑最小割。
    一个警卫向他可以看到的珠宝连inf边。
    起点向警卫连贿赂费用的边。
    珠宝向终点连价值的边。
    把所有珠宝的价值加起来再减去最大流可以得到答案。
    但是看到数据范围,这样子不太能做。
    考虑最大流。先旋转坐标系,使得每个警卫只能看到横/纵坐标都比它小的手办。
    问题转化成:有n个最多流出c[i]的水龙头,m个最多接受d[i]的点。
    一个水龙头只能向横/纵坐标小于等于他的点流,询问最大流。
    把水龙头按照x从小->大排序,在插入水龙头时更新网络流图。
    插入一个水龙头后插入所有接受点。
    显然每次向y坐标<=y且最大的点流最优。这样子接下来的点会更好流。
    可以用set简单实现。
    但是这样子的正确性不是很严格,本人不会证明。
    如果可以证明可以告诉博主。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    #define N 200010
    int n,m,w,ans,h;
    struct no{
    	int x,y,c;
    }a[N],b[N];
    int operator <(no x,no y){
    	return x.x<y.x||(x.x==y.x&&x.y<y.y);
    }
    set<no>s;
    signed main(){
    	scanf("%lld%lld%lld%lld",&n,&m,&w,&h);
    	for(int i=1;i<=n;i++){
    		int x,y,c;
    		scanf("%lld%lld%lld",&x,&y,&c);
    		x*=h;
    		y*=w;
    		a[i].x=x+y;
    		a[i].y=x-y;
    		a[i].c=c;
    		ans+=c;
    	}
    	for(int i=1;i<=m;i++){
    		int x,y,c;
    		scanf("%lld%lld%lld",&x,&y,&c);
    		x*=h;
    		y*=w;
    		b[i].x=x+y;
    		b[i].y=x-y;
    		b[i].c=c;
    	}
    	sort(a+1,a+n+1);
    	sort(b+1,b+m+1);
    	int j=1;
    	for(int i=1;i<=m;i++){
    		while(j<=n&&a[j].x<=b[i].x){
    			s.insert((no){a[j].y,j});
    			j++;
    		}
    		while(!s.empty()&&b[i].c){
    			auto it=s.lower_bound((no){b[i].y,0});
    			if(it==s.end())
    				break; 
    			int x=(*it).y,va=min(b[i].c,a[x].c);
    			b[i].c-=va;
    			a[x].c-=va;
    			ans-=va;
    			if(!a[x].c)s.erase(it);
    		}
    	}
    	printf("%lld
    ",ans);
    }
    
  • 相关阅读:
    eclipse使用
    模板模式

    异常处理
    内部类
    面向对象三大特征(三)--多态
    java双指针的简单理解
    简单易懂回溯算法
    《深入理解Java虚拟机》之(一、内存区域)
    Java笔记(第七篇 JDBC操作数据库)
  • 原文地址:https://www.cnblogs.com/ctmlpfs/p/13649572.html
Copyright © 2011-2022 走看看