首页 > 其他分享 >[SCOI2007] 蜥蜴 题解

[SCOI2007] 蜥蜴 题解

时间:2024-05-05 11:12:05浏览次数:16  
标签:nxt int 题解 st lv 入点 ans 蜥蜴 SCOI2007

发现实际上就是在求有多少只蜥蜴能逃出来。

发现可以将柱子拆成入点和出点两部分,自己的出点向别人的入点连边,自己的入点向自己的出点连边。最后再加一个超级源点 \(S\),连接所有有蜥蜴的柱子入点;再加一个超级汇点 \(T\),连接所有能够跳出地图的柱子。

我们猛然发现:这个问题不就是求最大流吗?

考虑每种边的容量:

  1. \(S\) 到入点。由于每个柱子至多有一只蜥蜴,所以容量为 \(1\)。

  2. 入点到出点。每个柱子只能向外跳 \(h_{i,j}\) 次,所以容量为 \(h_{i,j}\)。

  3. 出点到入点/ \(T\):这个没有限制,随便跳多少个都行,所以容量无限。

时间复杂度看似是 \(O(n^8)\),但果真如此吗?

考虑 \(d\) 最大为 \(4\),距离 \(\le 4\) 的一共有 \(49\) 个,所以实际边数至多为 \(49n^2\)(而且根本不可能跑满)。

所以时间复杂度为 \(O(49n^6)\)。

突然感觉用 \(FF\) 算法比 \(dinic\) 更优?

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=805,M=35005;
int n,m,de,s,t,id,h[N],d[N];
int k=1,to[M],w[M],nxt[M];
string st[N];int c[N],ans;
struct stone{int h,x,y;}a[N];
void add(int x,int y,int z){
	w[++k]=z;to[k]=y;
	nxt[k]=h[x];h[x]=k;
	w[++k]=0;to[k]=x;
	nxt[k]=h[y];h[y]=k;
}int bfs(){
    memset(c,-1,sizeof(c));
    queue<int>q;c[s]=0;
    q.push(s);d[s]=h[s];
    while(q.size()){
        int x=q.front();q.pop();
        for(int i=h[x];i;i=nxt[i]){
            int y=to[i];int  lv=w[i];
            if(lv>0&&c[y]==-1){
                c[y]=c[x]+1;d[y]=h[y];
                q.push(y);if(y==t) return 1;
            }
        }
    }return 0;
}int dfs(int x,int ans){
    if(x==t) return ans;
    int sum=ans;
    for(int i=d[x];i&&sum;i=nxt[i]){
        d[x]=i;int y=to[i];int  lv=w[i];
        if(lv<1||c[y]!=c[x]+1) continue;
        int  zjy=dfs(y,min(sum,lv));
        sum-=zjy;w[i]-=zjy;w[i^1]+=zjy;
    }return ans-sum;
}int dinic(){
    int re=0;
    while(bfs())
        re+=dfs(s,1e9);
    return re;
}int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cin>>n>>m>>de;
    for(int i=1;i<=n;i++){
        string t;cin>>t;t=" "+t;
        for(int j=1;j<=m;j++){
            if(t[j]=='0') continue;
            a[++id]={t[j]-'0',i,j};
        }
    }for(int i=1;i<=n;i++)
        cin>>st[i],st[i]=" "+st[i];
    s=id*2+1;t=id*2+2;
    for(int i=1;i<=id;i++){
        int ru=i*2-1,ch=i*2;
        double x=a[i].x,y=a[i].y;
        add(ru,ch,a[i].h);
        if(st[(int)x][(int)y]!='.')
            add(s,ru,1),ans++;
        if(x<=de||y<=de||x+de>n||y+de>m)
            add(ch,t,1e7);
        for(int j=1;j<=id;j++){
            if(i==j) continue;
            double z=a[j].x,w=a[j].y;
            if((x-z)*(x-z)+(y-w)*(y-w)<=de*de)
                add(ch,j*2-1,1e7);
        }
    }cout<<ans-dinic();
    return 0;
}

标签:nxt,int,题解,st,lv,入点,ans,蜥蜴,SCOI2007
From: https://www.cnblogs.com/chang-an-22-lyh/p/18173285/scoi2007-xiyi_tj

相关文章

  • 题解:AT_abc352_C [ABC352C] Standing On The Shoulders
    考场憋了很久,最后代码贼短……理想状态下,直接全排列解决问题。但是,\(1\len\le2\times10^5\),明显TLE,试都不用试的。咋优化呢?其实,前面的巨人只负责“打地基”,作为“塔尖儿”的巨人有且仅有1个。而前面地基随便排列,地基高度(他们的和)都不会变。所以,我们只需要枚举塔尖即......
  • 牛客小白月赛92 题解
    牛客小白月赛92题解A.获得木头签到\((x\times4)/2\times4=x\times8\)#include<bits/stdc++.h>usingnamespacestd;#definefffirst#definesssecond#definepbpush_back#defineall(u)u.begin(),u.end()#defineendl'\n'#definedebug(x......
  • 牛客 215E 黄魔法师 题解
    Description给出\(n,k\),求一个长度为\(n\)的数组\(a\),满足有恰好\(k\)对数对\((i,j)(1\leqi<j\leqn)\)满足\(a_i+a_j\)为完全平方数。如果不存在,输出\(-1\)。linkSolution显然如果\(k>\binom{n}{2}\)就一定无解。构造时会发现肯定要尽量弄成相同的......
  • 题解【[ABC155F] Perils in Parallel】(未完成)
    题目链接两个常规转化:灯的坐标与区间坐标都很大,不妨将其离散化,转化为\(1\simn\)的点与\(1\simn\)的操作区间。对于一段区间取反,可以理解为对一段区间异或\(1\),转化为在异或差分数组上操作,即差分数组\(diff_i=a_i\bigoplusa_{i-1}\),区间\([l,r]\)异或\(1\)转化为差......
  • 5月3日模拟赛题解(李时珍的皮肤衣 , 马大嘴的废话 , SSY的队列 , 清理牛棚 , 历史の研究)
    T1李时珍的皮肤衣发现是二进制进位,所以直接快速幂即可。#include<bits/stdc++.h>#defineint__int128inlineintread(){charch=getchar();intx=0,f=1;for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;for(;ch>='0'......
  • 题解:ssy的队列
    题目链接题目描述SSY是班集体育委员,总喜欢把班级同学排成各种奇怪的队形,现在班级里有\(N\)个身高互不相同的同学,请你求出这\(N\)个人的所有排列中任意两个相邻同学的身高差均不为给定整数\(M\)的倍数的排列总数。输入格式共三行:第一行为\(N\)第二行为\(N\)个不同的......
  • P10064 [SNOI2024] 公交线路 题解
    弱化版:CF1827EBusRoutes。对于\(n=2\)的情况可以判掉,剩下的情况取一个度数大于一的点作为根。首先发现如果叶子间满足条件,那么整棵树也满足条件。考虑叶子间什么时候满足条件,记点\(x\)通过最多一条路径可以到达的所有点的集合为\(S_x\),则需满足\(\forallx,y\in\mathbf......
  • [国家集训队] 矩阵乘法 题解
    发现实际上就是二维静态区间最大值,可以用整体二分维护。时间复杂度\(O((q+n^2)\log\max(a_{i,j})\logn^2)\)。#include<bits/stdc++.h>#definelllonglongusingnamespacestd;constintW=310005;constintQ=6e4+5;intn,q,w,ans[Q];intc[505][505],m;voidadd(i......
  • 题解【[ABC147F] Sum Difference】
    题目链接下为口胡题解:入手方向推导:直接考虑题目所给式子显然困难:\[w(S)=\sum_{i\inS}A_i-\sum_{i\notinS}A_i\]因为两个式子虽然相关但是都在变化,不妨转化为:\[w(S)=2\times\sum_{i\inS}A_i-\sum_{i=1}^nA_i\]这样只用求出有多少个不同的\(\sum_{i\inS}A_i\)。由于......
  • CF1968E.Cells Arrangement-构造(给个和题解不同的做法)
    link:https://codeforces.com/problemset/problem/1968/E题意:需要构造一个\(n\timesn\)的棋盘,在上面放\(n\)枚棋子,设集合\(\mathcal{H}\)表示两两之间曼哈顿距离构成的集合,要让\(|\mathcal{H}|\)最大。给出放棋子的方案。首先说说题解的做法…考虑把距离为奇数和偶数的......