题目
描述
有一个平面图(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; }