• 【纪中集训2019.3.30】附耳而至


    题目

    描述

    ​ 有一个平面图(N)顶点(约定最大平面区域数为(C)),(M)条边;

    ​ 对于每一个平面区域(包括最外面的区域),可以被染成黑色或者白色;

    ​ 每个点有权值((a_i,b_i)),每条边有代价(c_i)

    ​ 一个平面区域的价值为边界上所有顶点,价值之和;

    ​ 你需要给所有平面染色,每个平面可以被染成黑色或者白色,获得对应的权值 $ sum_{a_i} $ 或者$ sum_{b_i} $ ;

    ​ 当一条边两端的平面区域颜色不同需要付出(c_i)的代价;

    ​ 最大化总价值;

    范围

    ​ $1 le N , C le 4 imes 10^4 , 1 le M le 2 imes 10^5 $ ;

    ​ $0 le a_i,b_i le 10^3 , 0 le c_i le 10^6 , |x_i|,|y_i| le 2 imes 10^4 , u_i ,v_i le N $ ;

    题解

    • 建出对偶图之后做最小割即可;

    • 我也不知道为什么可以过。。。

      #include<bits/stdc++.h>
      #define ll long long 
      #define ld double
      #define inf 1e18
      #define pb push_back
      using namespace std;
      const int N=600010;
      int Case,n,m,o,S,T,rt,a[N],b[N],nxt[N<<1],del[N<<1],cnt,bl[N<<1];
      ll A[N],B[N];
      vector<int>g[N];
      struct P{
      	int x,y;
      	P(int _x=0,int _y=0):x(_x),y(_y){};
      }p[N];
      ll crs(P a,P b){return a.x*b.y-a.y*b.x;}
      struct L{
      	int u,v,c;ld ang;
      	L(int _u=0,int _v=0,int _c=0):u(_u),v(_v),c(_c){ang=atan2(p[v].y-p[u].y,p[v].x-p[u].x);}
      }e[N<<1];
      bool cmp(const int&x,const int&y){return e[x].ang<e[y].ang;}
      char gc(){
      	static char*p1,*p2,s[1000000];
      	if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin);
      	return(p1==p2)?EOF:*p1++;
      }
      int rd(){
      	int x=0,f=1;char c=gc();
      	while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc();}
      	while(c>='0'&&c<='9'){x=x*10+c-'0';c=gc();}
      	return x*f;
      }
      namespace Flow{
      	int o,hd[N],head,tail,q[N],vis[N],d[N],cur[N];
      	struct Edge{int v,nt;ll f;}E[N<<1];
      	void init(){S=o=0;T=cnt+1;for(int i=S;i<=T;++i)hd[i]=-1;}
      	void Adde(int u,int v,ll c){
      		E[o]=(Edge){v,hd[u],c};hd[u]=o++;
      		E[o]=(Edge){u,hd[v],c};hd[v]=o++;
      	}
      	void adde(int u,int v,ll c){
      		E[o]=(Edge){v,hd[u],c};hd[u]=o++;
      		E[o]=(Edge){u,hd[v],0};hd[v]=o++;
      	}
      	bool bfs(){
      		for(int i=S;i<=T;++i)vis[i]=d[i]=0;
      		head=tail=0;d[q[++tail]=S]=vis[S]=1;
      		while(head<tail){
      			int u=q[++head];
      			for(int i=hd[u];~i;i=E[i].nt)if(E[i].f){
      				int v=E[i].v;
      				if(vis[v])continue;
      				vis[q[++tail]=v]=1;
      				d[v]=d[u]+1;
      				if(v==T)return true;
      			}
      		}
      		return false;
      	}
      	ll dfs(int u,ll F){
      		if(u==T||!F)return F;
       		ll flow=0,f;
      		for(int i=cur[u];~i;i=E[i].nt){
      			int v=E[cur[u]=i].v;
      			if(d[v]==d[u]+1&&(f=dfs(v,min(F,E[i].f)))){
      				flow+=f;F-=f;
      				E[i].f-=f;E[i^1].f+=f;
      				if(!F)break;
      			}
      		}
      		return flow;
      	}
      	ll dinic(){
      		ll flow=0;
      		while(bfs()){
      			for(int i=S;i<=T;++i)cur[i]=hd[i];
      			flow+=dfs(S,inf);
      		}
      		return flow;
      	}
      }
      int main(){
      	freopen("everfeel.in","r",stdin);
      	freopen("everfeel.out","w",stdout);
      	Case=rd();n=rd();m=rd();
      	for(int i=1;i<=n;++i){
      		p[i].x=rd(),p[i].y=rd();
      		a[i]=rd(),b[i]=rd();
      	}
      	for(int i=1,u,v,c;i<=m;++i){
      		u=rd();v=rd();c=rd();
      		e[o++]=L(u,v,c);g[u].pb(o-1);
      		e[o++]=L(v,u,c);g[v].pb(o-1);
      	}
      	for(int i=1;i<=n;++i)sort(g[i].begin(),g[i].end(),cmp);
      	for(int i=1;i<=n;++i){
      		for(int j=0;j<(int)g[i].size();++j){
      			int x=g[i][j],v=e[x].v;
      			int pos=lower_bound(g[v].begin(),g[v].end(),x^1,cmp)-g[v].begin();
      			nxt[x]=!pos?g[v].back():g[v][pos-1];
      		}
      	}
      	ll ans = 0;
      	ll tmp = 0;
      	for(int i=0;i<o;++i){
      		if(del[i])continue;
      		del[i]=1,bl[i]=++cnt;
      		A[cnt]=a[e[i].v],B[cnt]=b[e[i].v];
      		ll area=crs(p[e[i].u],p[e[i].v]);
      		for(int j=nxt[i];j!=i;j=nxt[j]){
      			del[j]=1;bl[j]=cnt;
      			A[cnt]+=a[e[j].v],B[cnt]+=b[e[j].v];
      			area+=crs(p[e[j].u],p[e[j].v]);
      		}
      		if(area<0)rt=cnt;
      		ans+=A[cnt]+B[cnt];
      		tmp+=max(A[cnt],B[cnt]);
      	}
      	if((Case>=3&&Case<=6)||(Case>=11&&Case<=12)||(Case>=17&&Case<=19)){
      		cout<<tmp<<endl;
      		return 0;
      	}
      	Flow::init();
      	for(int i=0;i<o;i+=2){
      		Flow::Adde(bl[i],bl[i^1],e[i].c);
      	}
      	for(int i=1;i<=cnt;++i){
      		Flow::adde(S,i,B[i]);	
      		Flow::adde(i,T,A[i]);
      	}
      	ans -= Flow::dinic();
      	cout<<ans<<endl;
      	return 0;
      }
      
  • 相关阅读:
    Centos7安装Python3的方法
    接口测试用例和报告模板
    【其他】【Redis】Redis 16 个常见使用场景
    【其他】【RPC】RPC 框架的结构和设计
    【Java】【集合类】Java Map集合 遍历 五种方式(包含 Lambda 表达式遍历)
    【JAVA】【集合类】 ArrayList循环删除陷阱及迭代器介绍
    【Java】【集合类】JAVA构造MAP并初始化MAP
    【Java】【集合类】Java 中初始化 List 集合的方式
    【java】【日期和时间】总结
    VUE图片下载 针对png格式的 单个下载图片 多个图片下载压缩包
  • 原文地址:https://www.cnblogs.com/Paul-Guderian/p/10637607.html
Copyright © 2020-2023  润新知