zoukankan      html  css  js  c++  java
  • bzoj 4823 & 洛谷 P3756 老C的方块 —— 最小割

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4823

    https://www.luogu.org/problemnew/show/P3756

    巧妙建图;

    其实“俄罗斯方块”就是选择一条特殊边两边的方格,左右两边周围的六个中再各选两个;

    于是可以把图“四分”,特殊边两边的格子算两种,而且奇数行和偶数行恰好相反,然后两边围着的格子也算两种;

    然后不能有上面四种可选方格同时存在的情况,建出图来跑最小割即可。

    代码如下:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<map>
    #include<queue>
    using namespace std;
    int const xn=2e5+5,xm=2e6+5,inf=1e9;
    int C,R,n,hd[xn],ct=1,to[xm],nxt[xm],c[xm],dis[xn],cur[xn],S,T;
    map<int,int>mp[xn];
    struct N{int x,y;}p[xn];
    queue<int>q;
    int rd()
    {
      int ret=0,f=1; char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-')f=0; ch=getchar();}
      while(ch>='0'&&ch<='9')ret=ret*10+ch-'0',ch=getchar();
      return f?ret:-ret;
    }
    void ade(int x,int y,int z){to[++ct]=y; nxt[ct]=hd[x]; hd[x]=ct; c[ct]=z;}
    void add(int x,int y,int z){ade(x,y,z); ade(y,x,0);}
    int tp(int x,int y)
    {
      int d=y%4;
      if(x&1){if(d==1)return 1; if(d==2)return 2; if(d==3)return 4; if(!d)return 3;}
      else {if(d==1)return 3; if(d==2)return 4; if(d==3)return 2; if(!d)return 1;}
    }
    void addedge(int a,int b,int x,int y)
    {
      if(a==3&&b==1)add(n+x,y,inf);
      else if(a==1&&b==2)add(n+x,y,inf);
      else if(a==2&&b==4)add(n+x,y,inf);
    }
    bool bfs()
    {
      for(int i=S;i<=T;i++)dis[i]=0;
      dis[S]=1; q.push(S);
      while(q.size())
        {
          int x=q.front(); q.pop();
          for(int i=hd[x],u;i;i=nxt[i])
        if(!dis[u=to[i]]&&c[i])dis[u]=dis[x]+1,q.push(u);
        }
      return dis[T];
    }
    int dfs(int x,int fl)
    {
      //printf("x=%d fl=%d
    ",x,fl);
      if(x==T)return fl;
      int ret=0;
      for(int &i=cur[x],u;i;i=nxt[i])
        {
          if(dis[u=to[i]]!=dis[x]+1||!c[i])continue;
          int tmp=dfs(u,min(fl-ret,c[i]));
          if(!tmp)dis[u]=0;
          c[i]-=tmp; c[i^1]+=tmp;
          ret+=tmp; if(ret==fl)break;
        }
      return ret;
    }
    int main()
    {
      C=rd(); R=rd(); n=rd(); S=0; T=2*n+1;
      for(int i=1,x,y,w;i<=n;i++)
        {
          y=p[i].y=rd(); x=p[i].x=rd(); w=rd();
          mp[x][y]=i; add(i,n+i,w);
          int t=tp(p[i].x,p[i].y);
          if(t==3)add(S,i,inf);
          if(t==4)add(n+i,T,inf);
        }
      for(int i=1;i<=n;i++)
        {
          int x=p[i].x,y=p[i].y,t=tp(x,y);
          if(x>1&&mp[x-1][y]){int tt=tp(x-1,y); addedge(t,tt,i,mp[x-1][y]);}
          if(y>1&&mp[x][y-1]){int tt=tp(x,y-1); addedge(t,tt,i,mp[x][y-1]);}
          if(x<R&&mp[x+1][y]){int tt=tp(x+1,y); addedge(t,tt,i,mp[x+1][y]);}
          if(y<C&&mp[x][y+1]){int tt=tp(x,y+1); addedge(t,tt,i,mp[x][y+1]);}
        }
      int ans=0;
      while(bfs())
        {
          memcpy(cur,hd,sizeof hd);
          ans+=dfs(S,inf);
        }
      printf("%d
    ",ans);
      return 0;
    }
  • 相关阅读:
    开源项目cmdbuild-搭建
    开源项目cmdbuild-寄语
    四 上下文切换
    withRouter的作用和一个简单应用
    封装react组件:显示五星评价
    简单使用 Easy Mock-创建线上伪数据
    react中避免内存泄漏的方法
    react中constructor和super的使用
    使用swiper设计移动端轮播图(https://www.swiper.com.cn/)
    vuex模块化练习-购物车
  • 原文地址:https://www.cnblogs.com/Zinn/p/10162236.html
Copyright © 2011-2022 走看看