zoukankan      html  css  js  c++  java
  • BZOJ 4823 Luogu P3756 老C的方块 染色+最小割

    题面太长了请各位自行品尝—>老C的方块

    分析:

      我们要解决掉所有使人弃疗的组合,还要保证花费最小,容易想到最小割(当然你要是想费用流的话,我们就没办法定义流量了)

      我们来分析一下那些令人弃疗的组合,他们的规律:

      首先是两个和特殊边直接相邻的方块(以下简称轴方块),加上两侧各任意一个边缘方块,组成了令人弃疗的组合。

      所以我们有三种选择(准确地说其实只有两种,前两种本质一样):

      1. 将和特殊边左侧的轴方块相连的所有边缘方块都破坏掉。

      2. 将和特殊边右侧的轴方块相连的所有边缘方块都破坏掉。

      3. 破坏掉任意一个轴方块。

      我们还可以发现,特殊边两侧的部分相互独立。

      所以我们可以应用染色技巧,怎么染色?当然是按照坐标(i+j)的奇偶性将图染成两种颜色。

      之后从对于边缘方块及其轴方块,白点向黑点连边,流量为inf、

      相邻的轴方块,黑点向白点连边,容量为较小的那个的代价、

      之后S向白色边缘方块连边,容量为其代价,黑边缘方块向T连边,容量为其代价。

      跑最小割。

      细节很多,一着不慎满盘皆输!

    代码:

     1 #include<bits/stdc++.h>
     2 #define ms(a,x) memset(a,x,sizeof(a)) 
     3 using namespace std;int tot=0;
     4 const int N=100005,inf=0x3f3f3f3f;
     5 int S,T,n,m,k,h[N],c=1,q[N],d[N];
     6 struct node{int y,z,nxt;}e[N*20];
     7 struct kuai{int x,y,w,id;}p[N];
     8 void add(int x,int y,int z){
     9     e[++c]=(node){y,z,h[x]};h[x]=c;
    10     e[++c]=(node){x,0,h[y]};h[y]=c;
    11 } bool bfs(){
    12     int f=1,t=0;ms(d,-1);
    13     q[++t]=S;d[S]=0;
    14     while(f<=t){
    15         int x=q[f++];
    16         for(int i=h[x],y;i;i=e[i].nxt)
    17         if(d[y=e[i].y]==-1&&e[i].z) 
    18         d[y]=d[x]+1,q[++t]=y;
    19     } return (d[T]!=-1);
    20 } int dfs(int x,int f){
    21     if(x==T) return f;int w,tmp=0;
    22     for(int i=h[x],y;i;i=e[i].nxt)
    23     if(d[y=e[i].y]==d[x]+1&&e[i].z){
    24         w=dfs(y,min(e[i].z,f-tmp));
    25         if(!w) d[y]=-1;e[i].z-=w;
    26         e[i^1].z+=w;tmp+=w;
    27         if(tmp==f) return f;
    28     } return tmp;
    29 } void dinic(){
    30     while(bfs()) tot+=dfs(S,inf);
    31 } bool cpx(kuai a,kuai b){
    32     return a.x!=b.x?a.x<b.x:a.y<b.y;
    33 } bool cpy(kuai a,kuai b){
    34     return a.y!=b.y?a.y<b.y:a.x<b.x;
    35 } int main(){
    36     scanf("%d%d%d",&n,&m,&k);S=0;T=k+1;
    37     for(int i=1;i<=k;p[i].id=i,i++)
    38     scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].w);
    39     p[0].x=p[0].y=p[k+1].x=p[k+1].y=0;
    40     sort(p+1,p+k+1,cpx);
    41     for(int i=1;i<=k;i++)
    42     if(p[i+1].x==p[i].x&&p[i+1].y==p[i].y+1){
    43         if(((p[i].x+p[i].y)&1)==0)
    44         add(p[i].id,p[i+1].id,inf);
    45         else add(p[i+1].id,p[i].id,inf);
    46     } sort(p+1,p+k+1,cpy);
    47     for(int i=1,val;i<=k;i++){
    48         if(p[i+1].x!=p[i].x+1||p[i+1].y!=p[i].y)
    49         continue;
    50         if(p[i].x%2&&p[i].y%2==((p[i].x-1)/2)%2)
    51         continue;
    52         if(p[i].x%2) val=min(p[i].w,p[i+1].w);
    53         else val=inf;if(p[i].y%2)
    54         add(p[i+1].id,p[i].id,val);
    55         else add(p[i].id,p[i+1].id,val);
    56     } for(int i=1;i<=k;i++)
    57     if(((p[i].x-1)/2)%2==p[i].y%2){
    58         if((p[i].x+p[i].y)%2==0)
    59         add(S,p[i].id,p[i].w);
    60         else add(p[i].id,T,p[i].w);
    61     } dinic();
    62     printf("%d
    ",tot);return 0;
    63 }
    染色最小割
  • 相关阅读:
    wpf如何将图片设置为窗体的背景
    C#用Oracle.DataAccess中连接Oracle要注意版本问题!
    C#格式化数值结果表
    将字符串的16进制转换成byte[]
    Java各个类型与byte[]的转换
    记录下 Jquery的使用
    页面div与顶部有缝隙问题
    Js 转换Json返回的时间格式(转)
    Div垂直居中水平居中
    C# 日期格式大全
  • 原文地址:https://www.cnblogs.com/Alan-Luo/p/10251533.html
Copyright © 2011-2022 走看看