[BZOJ 1804] Flood
Link:
Solution:
不容易啊,第一道完全自己A掉的IOI题目.....
算法思想其实很简单:
模拟缩减的过程即可
将每条边转为2条有向边,每次找到最左边的边,沿着最外圈走一周,并将走过的边打上$vis$标记
最后那些正向和反向都被走过的边就是能留下的边(最后形成链的边)
难点在于如何实现在最外层走一周:
由于这是一个平面图,我们对每个点只要记录上下左右四个方向的边即可
又保证是顺时针转,因此尽量往左边走就能满足最外圈这个条件
(注意对$vis$数组更新的位置,否则可能在遇到链时死循环)
其实还有一种不带$log$的做法:
将平面图转化为对偶图,$bfs$每条边到边界的距离
如果两边的距离相等,这条边就计入答案(难点在建图)
待填坑
Code:
#include <bits/stdc++.h> using namespace std;
typedef pair<int,int> P;
#define X first
#define Y second
const int MAXN=4e5+; P nd[MAXN],tp[MAXN];
int n,m,dir[MAXN][],cnt[MAXN][],vis[MAXN][],res=;
int tot=,tdir[MAXN];
struct edge{int x,y,dir;} e[*MAXN];
bool cmp(edge a,edge b) //对边的排序
{
if(nd[a.x].X==nd[b.x].X)
if((a.dir== || a.dir==) && (b.dir== || b.dir==)) return true;
else if((a.dir== || a.dir==) && (b.dir== || b.dir==)) return false;
return nd[a.x].X<nd[b.x].X;
} void add_edge(int a,int b,int id)
{
if(nd[a].X==nd[b].X)
if(nd[a].Y<nd[b].Y) dir[a][]=b,dir[b][]=a,e[id].dir=;
else dir[a][]=b,dir[b][]=a,e[id].dir=;
else
if(nd[a].X<nd[b].X) dir[a][]=b,dir[b][]=a,e[id].dir=;
else dir[a][]=b,dir[b][]=a,e[id].dir=;;
} int Back(int x){return (x+)%;}
int Left(int x){return (x+)%;}
int Right(int x){return (x+)%;}
void Travel(int id)
{
int cur=e[id].y,d=e[id].dir,pre=e[id].x;cnt[pre][d]++;
tot=;tp[tot]=P(pre,cur);tdir[tot]=d;
while(cur!=e[id].x)
{
d=Left(d); //尽量往左走
while(!dir[cur][d] || vis[cur][d]) d=Right(d);
pre=cur;cur=dir[cur][d];cnt[pre][d]++;
tp[++tot]=P(pre,cur);tdir[tot]=d;
}
for(int i=;i<=tot;i++) //一定要最后一起打vis标记,否则可能死循环
vis[tp[i].X][tdir[i]]=vis[tp[i].Y][Back(tdir[i])]=true;
} int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++) scanf("%d%d",&nd[i].X,&nd[i].Y);
scanf("%d",&m);
for(int i=;i<=m;i++)
{
scanf("%d%d",&e[i].x,&e[i].y);
if(nd[e[i].x].X>nd[e[i].y].X) swap(e[i].x,e[i].y);
if(nd[e[i].x].Y>nd[e[i].y].Y) swap(e[i].x,e[i].y);
add_edge(e[i].x,e[i].y,i);
} sort(e+,e+m+,cmp);
for(int i=;i<=m;i++)
{
if(vis[e[i].x][e[i].dir]) continue; //已走过的边
Travel(i);
}
for(int i=;i<=m;i++)
if(cnt[e[i].x][e[i].dir] && cnt[e[i].y][Back(e[i].dir)]) res++;
printf("%d",res);
return ;
}
Review:
遇到平面图时(保证边两两不相交),一定要考虑其对偶图
[BZOJ 1804] Flood的更多相关文章
- 【BZOJ】初级水题列表——献给那些想要进军BZOJ的OIers(自用,怕荒废了最后的六月考试月,刷刷水题,水水更健康)
BZOJ初级水题列表——献给那些想要进军BZOJ的OIers 代码长度解释一切! 注:以下代码描述均为C++ RunID User Problem Result Memory Time Code_Le ...
- bzoj AC倒序
Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...
- BZOJ 2127: happiness [最小割]
2127: happiness Time Limit: 51 Sec Memory Limit: 259 MBSubmit: 1815 Solved: 878[Submit][Status][Di ...
- SYN Flood测试
由于工作需要对公司进行SYN Flood测试,在网上查了些资料,Youtube上找到最多的方法就是hping3工具来实现, 该工具已经预装在Kali下,具体操作用一条命令即可实现. hping3 -S ...
- BZOJ 3275: Number
3275: Number Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 874 Solved: 371[Submit][Status][Discus ...
- BZOJ 2879: [Noi2012]美食节
2879: [Noi2012]美食节 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 1834 Solved: 969[Submit][Status] ...
- bzoj 4610 Ceiling Functi
bzoj 4610 Ceiling Functi Description bzoj上的描述有问题 给出\(n\)个长度为\(k\)的数列,将每个数列构成一个二叉搜索树,问有多少颗形态不同的树. Inp ...
- BZOJ 题目整理
bzoj 500题纪念 总结一发题目吧,挑几道题整理一下,(方便拖板子) 1039:每条线段与前一条线段之间的长度的比例和夹角不会因平移.旋转.放缩而改变,所以将每条轨迹改为比例和夹角的序列,复制一份 ...
- 【sdoi2013】森林 BZOJ 3123
Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...
随机推荐
- 从零开始学习MXnet(一)
最近工作要开始用到MXnet,然而MXnet的文档写的实在是.....所以在这记录点东西,方便自己,也方便大家. 我觉得搞清楚一个框架怎么使用,第一步就是用它来训练自己的数据,这是个很关键的一步. 一 ...
- Spring学习--使用 utility scheme 定义集合及 p命名空间
util schema 定义集合: 使用基本的集合标签定义集合时 , 不能将集合作为独立的 Bean 定义 , 导致其他 Bean 无法引用该集合 , 所以无法在不同 Bean 之间共享集合. 可以用 ...
- HTTP缓存原理
http的缓存分为强制缓存和对比缓存,两者的区别在于,强制缓存只要设置的时间不过期,就可以直接拿去用,而不用向服务器再一次发送请求.而对比缓存不管缓存是否有效,都需要向服务器发送请求. 其过程如下: ...
- 关于CRC循环冗余校验的总结(C#)
1. 实验要求 (1)通过CRC(循环冗余校对)序列的计算,掌握C#语言中类的静态方法与动态方法的区别. (2)Shell与Windows Form 的通信作为扩展提高内容. 2. 实验内容 主要工 ...
- POJ 1064---二分搜索法
///2.假定一个解并判断是否可行 ///POJ1064 /** Q:有N条绳子,长度分别为Li,从中切割出k条长度相同的绳子, 这K条绳子最长能有多长?保留两位小数 A: 二分搜索模型. 条件C(x ...
- svn无法checkout大文件的解决办法
美术组同事checkout出现,在网络好的情况下,有同事更新下来了,后来在配置文件http.conf的最后加入下面压缩参数才解决问题,配置如下: <IfModule deflate_module ...
- 1552: [Cerc2007]robotic sort
这道题用splay写 先离散化数据保证按题目所述顺序来写 按原序作为键值建树 维护区间最小值去跑 每次将i的位置 和 n的位置x和y找出来后 将x旋转到root y旋转到x的有儿子 这时y的左子树就是 ...
- VC6.0显示行号的插件
VC6.0显示行号的插件,很好很强大的显行号插件,使用VC编程的朋友再也不用烦恼VC6.0没有行号的编程环境了. VC显示行号插件使用说明:1. 如果你的VC安装在C盘,请拷贝文件VC6LineNum ...
- linux C 中的volatile使用【转】
转自:http://blog.csdn.net/sukhoi27smk/article/details/38020583 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器 ...
- python学习笔记 IO 文件读写
读写文件是最常见的IO操作.python内置了读写文件的函数. 读写文件前,我们先必须了解一下,在磁盘上读写文件的功能都是由操作系统完成的,现代操作系统不允许普通的程序直接对磁盘进行操作,所以, 读写 ...