题目

描述

​ 给出一个\(n*m\)的网格,每个格子里的水管可能向四个方向都有接口;

​ 游戏的目的是不能让水管漏水,即所有接口都有另一个接口与之相接;

​ 你一步可以将一个格子中的水管旋转\(90^ {\circ}\),规定直线型的接口不能旋转;

​ 求最小的步数;

范围

​ \(nm \le 2000\);

题解

  • 对每个点拆成上右下左四个接口(令标号为0123),将格子黑白染色并将接口分别向源汇连边;

  • 对每种形状的水管分类讨论,用 \((a,b,w)\) 表示在内部连边,仅讨论黑格子,白格子类似:

    • 0 型:(0,1,1)(0,3,1)(0,2,2)
    • 01型:(0,2,1)(1,3,1)
    • 012型:(0,3,1)(2,3,1)(1,3,2)
    • 其他型:内部不需要连边
  • 主要思想是讨论每种形状转来转去时候的代价;

    #include<bits/stdc++.h>
    #define I(i,j,k) (k*n*m+(i-1)*m+j)
    #define inf 0x3f3f3f3f
    using namespace std;
    const int N=40010;
    int n,m,o,hd[N],S,T,que[N],head,tail,vis[N],dis[N];
    struct Edge{int v,nt,f,w;}E[N<<2];
    void adde(int u,int v,int c,int w){
    E[o]=(Edge){v,hd[u],c,w};hd[u]=o++;
    E[o]=(Edge){u,hd[v],0,-w};hd[v]=o++;
    }
    void add(int i,int j,int k1,int k2,int w){
    if((i+j)&1)adde(I(i,j,k1),I(i,j,k2),1,w);
    else adde(I(i,j,k2),I(i,j,k1),1,w);
    }
    bool spfa(){
    for(int i=S;i<=T;++i)vis[i]=0,dis[i]=inf;
    head=0;tail=1;vis[que[0]=T]=1;dis[T]=0;
    while(head!=tail){
    int u=que[head++];if(head==T)head=0;
    vis[u]=0;
    for(int i=hd[u];~i;i=E[i].nt)if(E[i^1].f){
    int v=E[i].v;
    if(dis[v]>dis[u]+E[i^1].w){
    dis[v]=dis[u]+E[i^1].w;
    if(!vis[v]){
    vis[v]=1,que[tail++]=v;
    if(tail==T)tail=0;
    }
    }
    }
    }
    return dis[S]!=inf;
    }
    int dfs(int u,int F){
    vis[u]=1;
    if(u==T||!F)return F;
    int flow=0,f;
    for(int i=hd[u];~i;i=E[i].nt){
    int v=E[i].v;
    if(!vis[v]&&dis[u]==dis[v]+E[i].w&&E[i].f&&(f=dfs(v,min(E[i].f,F)))){
    flow+=f;F-=f;
    E[i].f-=f;E[i^1].f+=f;
    if(!F)break;
    }
    }
    return flow;
    }
    int main(){
    // freopen("infinityloop.in","r",stdin);
    // freopen("infinityloop.out","w",stdout);
    scanf("%d%d",&n,&m);
    S=0;T=n*m*4+1;
    for(int i=S;i<=T;++i)hd[i]=-1;
    int mxf=0;
    for(int i=1;i<=n;++i)
    for(int j=1;j<=m;++j)if((i+j)&1){
    if(i!=1)adde(I(i,j,0),I(i-1,j,2),1,0);
    if(j!=1)adde(I(i,j,3),I(i,j-1,1),1,0);
    if(i!=n)adde(I(i,j,2),I(i+1,j,0),1,0);
    if(j!=m)adde(I(i,j,1),I(i,j+1,3),1,0);
    }
    int mx1=0,mx2=0;
    for(int i=1;i<=n;++i)
    for(int j=1;j<=m;++j){
    int x;scanf("%d",&x);
    if((i+j)&1)mx1+=__builtin_popcount(x);
    else mx2+=__builtin_popcount(x);
    for(int k=0;k<4;++k)if(x>>k&1){
    if((i+j)&1)adde(S,I(i,j,k),1,0);
    else adde(I(i,j,k),T,1,0);
    }
    switch (x){
    case 1:add(i,j,0,1,1);add(i,j,0,3,1);add(i,j,0,2,2);break;
    case 2:add(i,j,1,0,1);add(i,j,1,2,1);add(i,j,1,3,2);break;
    case 4:add(i,j,2,1,1);add(i,j,2,3,1);add(i,j,2,0,2);break;
    case 8:add(i,j,3,0,1);add(i,j,3,2,1);add(i,j,3,1,2);break; case 3:add(i,j,0,2,1);add(i,j,1,3,1);break;
    case 6:add(i,j,1,3,1);add(i,j,2,0,1);break;
    case 9:add(i,j,0,2,1);add(i,j,3,1,1);break;
    case 12:add(i,j,2,0,1);add(i,j,3,1,1);break; case 7:add(i,j,0,3,1);add(i,j,2,3,1);add(i,j,1,3,2);break;
    case 11:add(i,j,1,2,1);add(i,j,3,2,1);add(i,j,0,2,2);break;
    case 13:add(i,j,0,1,1);add(i,j,2,1,1);add(i,j,3,1,2);break;
    case 14:add(i,j,1,0,1);add(i,j,3,0,1);add(i,j,2,0,2);break; //case 0:break;
    //case 5:break;
    //case 10:break;
    //case 15:break;
    }
    }
    if(mx1!=mx2){puts("-1");return 0;}
    int flow=0,cost=0,f;
    while(spfa()){
    do{
    for(int i=S;i<=T;++i)vis[i]=0;
    f=dfs(S,inf);
    flow+=f;
    cost+=f*dis[S];
    }while(vis[T]);
    }
    if(flow!=mx1)puts("-1");
    else printf("%d\n",cost);
    return 0;
    }

【uoj336】【清华集训2017】无限之环的更多相关文章

  1. BZOJ.5120.[清华集训2017]无限之环(费用流zkw 黑白染色)

    题目链接 LOJ 洛谷 容易想到最小费用最大流分配度数. 因为水管形态固定,每个点还是要拆成4个点,分别当前格子表示向上右下左方向. 然后能比较容易地得到每种状态向其它状态转移的费用(比如原向上的可以 ...

  2. [清华集训2017]无限之环(infinityloop)

    description 题面 solution 一开始的思路是插头\(DP\),然而复杂度太高 考虑将网格图黑白染色后跑费用流 流量为接口数,费用为操作次数 把一个方格拆成五个点,如何连边请自行脑补 ...

  3. LOJ 2321 清华集训2017 无限之环 拆点+最小费用最大流

    题面:中文题面,这里不占用篇幅 分析: 看到题面,我就想弃疗…… 但是作为任务题单,还是抄了题解…… 大概就是将每个格子拆点,拆成五个点,上下左右的触点和一个负责连源汇点的点(以下简称本点). 这个这 ...

  4. Loj #2321. 「清华集训 2017」无限之环

    Loj #2321. 「清华集训 2017」无限之环 曾经有一款流行的游戏,叫做 *Infinity Loop***,先来简单的介绍一下这个游戏: 游戏在一个 \(n \times m\) 的网格状棋 ...

  5. [LOJ#2330]「清华集训 2017」榕树之心

    [LOJ#2330]「清华集训 2017」榕树之心 试题描述 深秋.冷风吹散了最后一丝夏日的暑气,也吹落了榕树脚下灌木丛的叶子.相识数年的Evan和Lyra再次回到了小时候见面的茂盛榕树之下.小溪依旧 ...

  6. [LOJ#2329]「清华集训 2017」我的生命已如风中残烛

    [LOJ#2329]「清华集训 2017」我的生命已如风中残烛 试题描述 九条可怜是一个贪玩的女孩子. 这天她在一堵墙钉了 \(n\) 个钉子,第 \(i\) 个钉子的坐标是 \((x_i,y_i)\ ...

  7. Loj #2331. 「清华集训 2017」某位歌姬的故事

    Loj #2331. 「清华集训 2017」某位歌姬的故事 IA 是一名会唱歌的女孩子. IOI2018 就要来了,IA 决定给参赛选手们写一首歌,以表达美好的祝愿.这首歌一共有 \(n\) 个音符, ...

  8. Loj #2324. 「清华集训 2017」小 Y 和二叉树

    Loj #2324. 「清华集训 2017」小 Y 和二叉树 小Y是一个心灵手巧的OIer,她有许多二叉树模型. 小Y的二叉树模型中,每个结点都具有一个编号,小Y把她最喜欢的一个二叉树模型挂在了墙上, ...

  9. Loj 2320.「清华集训 2017」生成树计数

    Loj 2320.「清华集训 2017」生成树计数 题目描述 在一个 \(s\) 个点的图中,存在 \(s-n\) 条边,使图中形成了 \(n\) 个连通块,第 \(i\) 个连通块中有 \(a_i\ ...

  10. 【UOJ#340】【清华集训2017】小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划)

    [UOJ#340][清华集训2017]小 Y 和恐怖的奴隶主(矩阵快速幂,动态规划) 题面 UOJ 洛谷 题解 考虑如何暴力\(dp\). 设\(f[i][a][b][c]\)表示当前到了第\(i\) ...

随机推荐

  1. 限流——spring-cloud-zuul-ratelimit

    先留个坑,慢慢补 git代码Demo:https://github.com/islowcity/spring-cloud-zuul-ratelimiter.git 有时间再写分析

  2. 运行supervisord -c /etc/supervisor/supervisord.conf 出错,解决办法

    坑都让我踩了...... 1 supervisord -c /etc/supervisor/supervisord.conf 什么意思? 答:手动启动:supervisord        具体详见 ...

  3. Node.js系列-express(下)

    前言 距上次更新博客又两个月多了,这两个月内除了上班时间忙公司的项目外,下班后也没有闲着,做了点外包,有小程序的,管理端的项目.也可能那段时间做的外包项目也都比较急,所以晚上都搞到一点左右睡,严重的压 ...

  4. win8系统本地服务网络受限cpu占用率过高解决方案

    今天更新软件时突然就打不开软件了,接着cpu就飙升. 打开任务管理器看到是“本地服务网络受限”这么一个东西占用的cpu最高. 在网上找到的解决方案无效的: 1.关闭家庭组(服务里的homegroup· ...

  5. UPC-5063-二分图最大匹配

    好吧二分图的最小点覆盖=最大匹配 这道题也就变成模板题了... 写一个提醒,在写二分图时,尽量清零操作清空为-1,比如这个题,匹配数组girl[]如果清空为0,代表每个点都与0点连接,但是实际上是并没 ...

  6. 通过LVM给Linux扩容

    主要参考以下两篇文章: 1:https://www.cnblogs.com/sixiweb/p/3360008.html 2:https://wenku.baidu.com/view/42deee1a ...

  7. opencv学习笔记(三)

    imread()读入图,第一个参数,const string&类型的filename,填我们需要载入的图片路径名, 第二个参数,int类型的flags,为载入标识,它指定一个加载图像的颜色类型 ...

  8. XSS编码与绕过

     XSS编码与绕过 0x00 背景 对于了解web安全的朋友来说,都知道XSS这种漏洞,其危害性不用强调了.一般对于该漏洞的防护有两个思路:一是过滤敏感字符,诸如[<,>,script,' ...

  9. [区块链]POW 与POS

    POW:全称Proof ofWork,工作证明. 这是什么意思呢?就是说,你能获得多少货币,取决于你挖矿贡献的有效工作,也就是说,你电脑性能越好,分给你的矿就会越多,这就是根据你的工作证明来执行货币的 ...

  10. error eslint@5.12.0: The engine "node" is incompatible with this module.

    初始化 react项目时报错: error eslint@5.12.0: The engine "node" is incompatible with this module. E ...