解题:SCOI 2007 蜥蜴

题面

拆点跑最大流

所有能跑出去的点连向汇点,容量为inf

原点连向所有初始有蜥蜴的点,容量为1

每根柱子拆成两个点“入口”和“出口”,入口向出口连容量为高度的边,出口向别的有高度的柱子的入口连容量为高度的边

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=1000,M=100000,inf=1e9;
 7 int n,m,d,f,b,s,t,t1,t2,t3,cnt,tot,ans;
 8 int p[N],pp[N],dep[N],que[N],idx[N][N];
 9 int noww[M],goal[M],flow[M];
10 char mapp[N][N];
11 void Link(int f,int t,int v)
12 {
13     noww[++cnt]=p[f],p[f]=cnt;
14     goal[cnt]=t,flow[cnt]=v;
15     noww[++cnt]=p[t],p[t]=cnt;
16     goal[cnt]=f,flow[cnt]=0;
17 }
18 int Dis(int a,int b,int c,int d)
19 {
20     return (a-c)*(a-c)+(b-d)*(b-d);
21 }
22 void Init(int st,int ed)
23 {
24     for(int i=1;i<=ed;i++)
25         pp[i]=p[i],dep[i]=-1;
26     dep[st]=0,que[f=b=0]=st;
27 }
28 bool Layering(int st,int ed)
29 {
30     Init(st,ed);
31     while(f<=b)
32     {
33         int tn=que[f++];
34         for(int i=pp[tn];i;i=noww[i])
35             if(dep[goal[i]]==-1&&flow[i])
36                 dep[goal[i]]=dep[tn]+1,que[++b]=goal[i];
37     }
38     return ~dep[ed];
39 }
40 int Augmenting(int nd,int ed,int mn)
41 {
42     if(nd==ed||!mn) return mn;
43     int tmp=0,tep=0;
44     for(int i=pp[nd];i;i=noww[i])
45     {
46         pp[nd]=i;
47         if(dep[goal[i]]==dep[nd]+1)
48             if(tep=Augmenting(goal[i],ed,min(mn,flow[i])))
49             {
50                 flow[i]-=tep,mn-=tep;
51                 flow[i^1]+=tep,tmp+=tep;
52                 if(!mn) break;
53             }
54     }
55     return tmp;
56 }
57 int Dinic_Maxflow(int st,int ed)
58 {
59     int ret=0;
60     while(Layering(st,ed))
61         ret+=Augmenting(st,ed,inf);
62     return ret;
63 }
64 int main ()
65 {
66     scanf("%d%d%d",&n,&m,&d);
67     s=2*n*m+1,t=s+1,cnt=1;
68     for(int i=1;i<=n;i++)
69     {
70         scanf("%s",mapp[i]+1);
71         for(int j=1;j<=m;j++)
72             idx[i][j]=++tot;
73     }
74     for(int i=1;i<=n;i++)
75         for(int j=1;j<=m;j++)
76             if(mapp[i][j]!=‘0‘)
77             {
78                 Link(idx[i][j],idx[i][j]+n*m,mapp[i][j]-‘0‘);
79                 if(i-d<1||i+d>n||j-d<1||j+d>m)
80                     Link(idx[i][j]+n*m,t,inf);
81                 else
82                     for(int k=1;k<=n;k++)
83                         for(int h=1;h<=m;h++)
84                             if(Dis(i,j,k,h)<=d*d&&(i!=k||j!=h)&&mapp[k][h]!=‘0‘)
85                                 Link(idx[i][j]+n*m,idx[k][h],mapp[i][j]-‘0‘);
86             }
87     for(int i=1;i<=n;i++)
88     {
89         scanf("%s",mapp[i]+1);
90         for(int j=1;j<=m;j++)
91             if(mapp[i][j]==‘L‘) ans++,Link(s,idx[i][j],1);
92     }
93     printf("%d\n",ans-Dinic_Maxflow(s,t));
94     return 0;
95 }

原文地址:https://www.cnblogs.com/ydnhaha/p/10291784.html

时间: 2024-10-10 20:10:24

解题:SCOI 2007 蜥蜴的相关文章

BZOJ 1066 SCOI 2007 蜥蜴 最大流

题目大意:给出一张图,每一个点有一个寿命,当有这个寿命值个蜥蜴经过后这个点就会消失,一个蜥蜴可以跳到距离不超过d的点上,问最少有多少只蜥蜴无法跳出这张图. 思路:我们将每个点拆点,然后限制流量为这个点的寿命,之后源点向每个蜥蜴连边,互相能够到达的点之间连边,能够跳出这个图的点和汇点连边,跑最大流就是这个图中最多能够跑出去的蜥蜴数量,最后在用总数减去就是最少不能逃出去的数量. CODE: #include <cmath> #include <queue> #include <c

[BZOJ 1072][SCOI 2007]排列perm

题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=1072 这题范围小,s的长度不超过10,如果用二进制表示每一位数字是否被选择到的话,二进制最大不超过2^10,可以用状压DP做. 我们把这题分两步走 第一步,把输入的字符串s中所有的数字都当成不同的,在这种情况下求出方案总数 用f[S][j]表示当前每一位数字是否选到的二进制状态为S,拼出的数mod d=j的方案数. 决策就是可以从所有没有被选到的数字中,选择一个数放到之前拼好的数

图论(网络流):SCOI 2007 修车

同一时刻有N位车主带着他们的爱车来到了汽车维修中心.维修中心共有M位技术人员,不同的技术人员对不同的车进行维修所用的时间是不同的.现在需要安排这M位技术人员所维修的车及顺序,使得顾客平均等待的时间最小. 说明:顾客的等待时间是指从他把车送至维修中心到维修完毕所用的时间. 输入 第一行有两个数M,N,表示技术人员数与顾客数. 接下来n行,每行m个整数.第i+1行第j个数表示第j位技术人员维修第i辆车需要用的时间T. 输出 最小平均等待时间,答案精确到小数点后2位. 样例 repair.in 2 2

BZOJ 1069 SCOI 2007 最大土地面积 凸包+旋转卡壳

题目大意:给出平面上的一些点,求其中四个点的最大四边形的面积. 思路:简单yy一下发现这些点肯定都在凸包上,先求个凸包.然后直接暴力肯定是不行的,我们需要一个O(n^2)的做法,比较简单的想法是枚举最后要求的四边形的一条对线,那么这个四边形就被分割成了两个三角形,剩下两个点与这条线组成的三角形的面积和就是答案. 按照旋转卡壳的思想不难发现,这两个点都是单调的.所以枚举对角线然后扫n圈就可以了. CODE: #define _CRT_SECURE_NO_DEPRECATE #include <cm

BZOJ SCOI 2007 修车 费用流

题目大意:有一些车和一些修车的人,给出每个人修每个车的时间,问所有人等待的最短平均时间是多少. 思路:记得POJ有一个和这个很像的题,做法是一样的.对于每个人修车的时候,我们只考虑他修车的时间对在它之后修车的人的时间的影响,因此我们只要考虑每一辆车是倒数第几个修的就可以了,然后朴素的建图,跑朴素的费用流,就可以过. CODE: #include <queue> #include <cstdio> #include <cstring> #include <ioman

[SCOI 2007] 排列

[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1072 [算法] 状压DP [代码] #include<bits/stdc++.h> using namespace std; #define MAXD 1000 const int MAXS = 2048; int i,j,k,T,len,d,MASK; char s[20]; long long f[MAXS][MAXD]; long long ans; long long f

[SCOI 2007] 修车

[题目链接] https://www.lydsy.com/JudgeOnline/problem.php?id=1070 [算法] 首先 , 我们发现 , 在倒数第i个修车会对答案产生i * k的贡献 将每辆车建一个点 , 每名技术人员建n个点 ,将车与技术人员连边 , 第i个技术人员的第j个点与第k辆车连边表示k是i修的倒数第j辆车 然后在这张图上求最小费用最大流 , 即可 时间复杂度 : O(Costflow(NM , N ^ 2M)) [代码] #include<bits/stdc++.h

[省选]省选知识点进度

联赛之后记录一下自己的知识点学习情况(按开始时间先后顺序) 可持久化数据结构 [BZOJ 3123]森林 树上主席树 启发式合并 LCA [BZOJ 4826]影魔 区间修改主席树 标记永久化 [BZOJ 2735]世博会 主席树 切比雪夫距离转曼哈顿距离 [BZOJ 3166]Alo 可持久化01Trie [BZOJ 3689]异或之 可持久化01Trie [BZOJ 3261]最大异或和 可持久化01Trie 树套树 [COGS 257]动态排名系统 树状数组套主席树 [BZOJ 2141]

UVa 1225 - Digit Counting - ACM/ICPC Danang 2007 解题报告

1.题目大意 把前n$n\le 10000$个整数顺次写在一起:12345678910111213……计算0~9各出现了多少次. 2.思路 第一想法是打表,然而觉得稍微有点暴力.不过暂时没有想到更好的办法了,写完看了一下其它人的思路好像也差不多是打表的思路. 3.应注意的问题 (1)首先是格式问题,我第一次提交的时候PE了,因为没有意识到空格也会有影响.最开始我的最后一段代码是: for(i=0;i<10;i++) printf("%d ",s[n][i]); printf(&q