【纪中集训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 \times 10^4 \ , \ 1 \le M \le 2 \times 10^5 $ ;

​ $0 \le a_i,b_i \le 10^3 \ , \ 0 \le c_i \le 10^6 , |x_i|,|y_i| \le 2 \times 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;
    }
    
posted @ 2019-04-01 17:18  大米饼  阅读(215)  评论(0编辑  收藏  举报