首页 > 其他分享 >[ABC205F] Grid and Tokens 题解

[ABC205F] Grid and Tokens 题解

时间:2023-06-05 13:36:10浏览次数:54  
标签:连边 head idx int 题解 Tokens 权为 Grid 入点

Grid and Tokens

题目大意

给定 \(n\) 个点和一个 \(H\times W\) 的网格,每个点可以放置在 \((A_i,B_i)\) 到 \((C_i,D_i)\) 的矩形中或不放,每一行或一列只能放置一个点,求最多能放多少个点。

思路分析

首先看数据范围,再结合题目给的限制条件,容易发现这是一道网络流。

考虑建图,因为行和列存在限制条件而网格中的点不存在,所以可以考虑将每一行和每一列分别建成一个点。再建立一个超级源点和超级汇点,源点向行连边权为 \(1\) 的边,列向汇点连边权为 \(1\) 的边。 表示每一行和每一列只能放一个点的限制条件。

对于一个点的矩形放置范围,可以转换为行 \(A_i\sim C_i\) 向该点连边权为 \(1\) 的边,该点向列 \(B_i\sim D_i\) 连边权为 \(1\) 的边,表示每一行和每一列对于点的匹配。

同时,点存在容量的限制,所以要将点拆成入点和出点,再连边。

综上所述,建图过程如下:

  • 建立源点,汇点。

  • 对于每一行和每一列建立一个点,源点向行连边权为 \(1\) 的边,列向汇点连边权为 \(1\) 的边。

  • 对于每一个点,建立入点和出点,入点向出点连边权为 \(1\) 的边,行 \(A_i\sim C_i\) 向入点连边权为 \(1\) 的边,出点向列 \(B_i\sim D_i\) 连边权为 \(1\) 的边。

因为流网络是单位网络,所以时间复杂度为 \(O(n^3)\)。(\(n,H,W\) 同阶)

代码

#include <iostream>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <queue>

using namespace std;
const int N=200100;
#define inf 0x3f3f3f3f

int n,m,k,idx=1,S,T,in1,in2,in3,in4,cnt;
int to[N],nxt[N],head[N],w[N];
int cur[N],d[N];

queue <int> q;

void add(int u,int v,int c){
    idx++;to[idx]=v;nxt[idx]=head[u];head[u]=idx;w[idx]=c;
    idx++;to[idx]=u;nxt[idx]=head[v];head[v]=idx;w[idx]=0;
}

bool bfs(){
    memset(d,-1,sizeof d);
    while(!q.empty()) q.pop();
    cur[S]=head[S];
    q.push(S);d[S]=0;
    while(!q.empty()){
        int now=q.front();q.pop();
        for(int i=head[now];i;i=nxt[i]){
            int v=to[i];
            if(~d[v]||!w[i]) continue;
            d[v]=d[now]+1;
            cur[v]=head[v];
            if(v==T) return 1;
            q.push(v);
        }
    }
    return 0;
}

int dfs(int s,int lim){
    if(s==T) return lim;
    int flow=0;
    for(int i=cur[s];i&&flow<lim;i=nxt[i]){
        int v=to[i];cur[s]=i;
        if(d[v]!=d[s]+1||!w[i]) continue;
        int t=dfs(v,min(w[i],lim-flow));
        if(!t) d[v]=-1;
        w[i]-=t;w[i^1]+=t;flow+=t;
    }
    return flow;
}

int dinic(){
    int ans=0,flow=0;
    while(bfs()) while(flow=dfs(S,inf)) ans+=flow;
    return ans;
}

int main(){
    scanf("%d%d%d",&n,&m,&k);
    S=N-5;T=N-6;cnt=n+m+1;
    for(int i=1;i<=n;i++) add(S,i,1);//源点->行
    for(int i=n+1;i<=n+m;i++) add(i,T,1);//列->汇点
    for(int i=1;i<=k;i++){
        scanf("%d%d%d%d",&in1,&in2,&in3,&in4);
        for(int i=in1;i<=in3;i++) add(i,cnt,1);//行->入点
        for(int i=n+in2;i<=n+in4;i++) add(cnt+1,i,1);//出点->列
        add(cnt,cnt+1,1);//入点->出点
        cnt+=2;
    }
    cout<<dinic()<<'\n';
    return 0;
}

标签:连边,head,idx,int,题解,Tokens,权为,Grid,入点
From: https://www.cnblogs.com/TKXZ133/p/17457548.html

相关文章

  • [ABC201E] Xor Distances 题解
    XorDistances题目大意给定一颗带边权无根树,定义\(\text{dis}(i,j)\)表示\(i,j\)两点在树上的最短路径的边权的异或和。求:\[\sum_{i=1}^n\sum_{j=i+1}^n\text{dis}(i,j)\]思路分析首先,容易证明:\[\text{dis}(i,j)=\text{dis}(i,x)\oplus\text{dis}(x,j)\]这个式子告诉我......
  • [ABC202E] Count Descendants 题解
    CountDescendants题目大意给定一颗以\(1\)为根的树,多次询问求某点的子树中深度为给定值的点的个数。思路分析对于每个深度开一个vector,从大到小存下这个深度的所有点的dfs序开始值和结束值,询问时只需要在对应深度的vector中二分作差即可。代码#include<iostream>#......
  • [ABC204E] Rush Hour 2 题解
    RushHour2题目大意给定一张无向图,边带两个参数\(c_i,d_i\),在\(t\)时间时经过第\(i\)条边所需的时间是\(c_i+\lfloor\frac{d_i}{t+1}\rfloor\),求在时间\(0\)时出发,在每个点可以停留非负整数时间,从点\(1\)到点\(n\)所需的最短时间。思路分析首先,容易发现在时间\(......
  • P2487 拦截导弹 题解
    拦截导弹题目大意给定若干元素,每个元素有\(3\)个属性\(t_i,h_i,v_i\),求出一个使得对于\(\foralli,j,i>j\),\(t_i>t_j,h_i\leh_j,v_i\lev_j\)均成立的最长的子序列\(a\)的长度。并计算每个元素在所有的可能的\(a\)方案中的出现概率。思路分析先看第一个问题:按\(......
  • P5012 水の数列 题解
    水の数列题目大意对于给定的数列\(a\),选择一个数\(x\),定义其得分为数列中所有小于等于\(x\)的数形成的若干个连续区间的平方和除以\(x\)所得到的数。现进行多次询问,每次询问给定两个数\(l,r\),要求出一个得分最大的\(x\),满足数列中所有小于等于\(x\)的数形成的若干个......
  • [ABC201D] Game in Momotetsu World 题解
    GameinMomotetsuWorld题目大意在一个\(n\timesm\)的网格中,存在红色和蓝色两种格子,红色格子用-表示,蓝色格子用+表示。现在Takahashi和Aoki要在这个网格中进行游戏,游戏的规则如下:初始时,有一枚棋子摆放在左上角,即\((1,1)\)的位置。两名玩家的分数均为\(0\)。......
  • P2048 超级钢琴 题解
    超级钢琴题目大意求出序列中长度在\([L,R]\)中的所有区间的区间和前\(k\)大的区间的区间和。思路分析暴力做法是把所有符合条件的区间扔进堆里,再弹出\(k\)个,时间复杂度\(O((n^2+k)\logn)\),可以拿到\(20\text{pts}\)的好成绩。但真的有必要全部加进去吗?不!我们设五......
  • P5445 路灯 题解
    路灯题目大意在\(n+1\)个站点之间有\(n\)盏路灯,给定\(0\)时刻所有路灯的亮灭情况,在接下来的\(q\)个时刻,每时刻会发生以下两种事件之一:切换某一盏路灯的亮灭。询问两点之间存在多少时刻使得两点之间的路灯全部亮起。思路分析一道不错的数据结构。首先分析题目......
  • Mysql 主从备份 Last_Errno: 1146 Last_Error: Error executing row event: 错误问题
    本人在做主从备份的时候发现了此问题! 1主数据库是已经把这个表删除了丛数据库也是没有备份这个表但是一直报这个错原因是bin-log日志有这个表 但是没记录到已经把这个表删除了 主从表同步实际从库是根据主库的bin-log二进制的SQL进行执行的 这是Mysql的一个BUG1......
  • erlang实现长连接管理问题解决
    具体参见:http://www.metabrew.com/article/a-million-user-comet-application-with-mochiweb-part-1/1.    erlang进程增加了休眠特性hibernate,支持连接从20w->70w;如上面的文章里面所说,使用hibernate后支撑的长连接飞涨。2.    40w时系统出现异常。查看系统日志发现socket......