【u209】轰炸
Time Limit: 1 second
Memory Limit: 128 MB
【问题描述】
小y是苏联的总书记。
苏联有n个城市,某些城市之间修筑了公路。任意两个城市都可以通过公路直接或者间接到达。
小y发现有些公路被毁坏之后会造成某两个城市之间无法互相通过公路到达。这样的公路就被称为dangerous pavement。
为了防止美帝国对dangerous pavement进行轰炸,造成某些城市的地面运输中断,小y决定在所有的dangerous pavement驻扎重兵。可是到
底哪些是dangerous pavement呢?你的任务就是找出所有这样的公路。
【输入格式】
第一行n,m(1<=n<=150, 1<=m<=5000),分别表示有n个城市,总共m条公路。 以下m行,每行两个整数a, b,表示城市a和城市b之间修筑了直接的公路。
【输出格式】
输出有若干行。 每行包含两个数字a,b(a<b),表示是dangerous pavement。 请注意:输出时,所有的数对必须按照a从小到大排序输出;如果a相同,则根据b从小到大排序。
Sample Input1
6 6
1 2
2 3
2 4
3 5
4 5
5 6
Sample Output1
1 2
5 6
【题解】
这道题用tarjan来做。
tarjan的作用在于缩点。即把那些能够互相到达的点给缩成一个点。比如下图
上图中的2,3,4,5为一个强连通分量。每两个点之间都有两条路径可以到达。所以不会满足重要公路的定义。
然后执行完tarjan算法之后。
1,2,3,4,5,6的新编号会变为3,2,2,2,2,1。
则对于每一条边。
只要bianhao[x]!=bianhao[y]。这条路径就是一条重要路径。
这里的bianhao[i]是缩点结束之后i新的编号;
然后一开始把输入的点按照题目的要求用比较函数排序就好
一开始不能写using namespace std;
因为好像next在加入上面这一句之后变成一个关键字了。 除了tarjan算法之外。你也可以枚举所有的边。假设其是关键路径。然后尝试着删掉它。然后
就从任意一个点开始遍历。看一下能不能到达所有的节点.如果不能则是关键路径否则不是。我之前做的时候
是这样做的。好像可以过。
当然。下面只提供tarjan算法的程序。
【代码】
#include <cstdio>
#include <cstring>
#include <algorithm> //sort函数包含在algorithm头文件当中 struct bian //这个结构体是为了方便排序。
{
int x, y;
}; bian a[5001]; //这是5000条边
int n, m, first[151], next[10001], en[10001], totm = 0, w[151][151] = { 0 }; //用邻接表来存储某个点的出度信息
int dfn[151], low[151], num = 0, stack[151], zzz[151], tot = 0, bianhao[151];//这是用于实现tarjan算法的数组
//zzz[i]表示i号节点在栈中的位置。
bool flag[151]; //记录某个节点是否访问过。 void input_data()
{
scanf("%d%d", &n, &m);//输入n个点m条边
for (int i = 1; i <= m; i++)
{
int x, y;
scanf("%d%d", &x, &y);
if (x > y) //因为要求输出的时候小的输出在前面。所以在输入的时候就进行一下处理。
{
int t = x; x = y; y = t;
}
a[i].x = x;//用邻接表来存储这张图。
a[i].y = y;
w[x][y] = w[y][x] = 1;
totm++;
next[totm] = first[x];
first[x] = totm;
en[totm] = y;
totm++;
next[totm] = first[y];
first[y] = totm;
en[totm] = x;
}
} int min(int a, int b) //获取a和b中的较小值。
{
return a > b ? b : a;
} void push(int what) //把x这个元素放入栈顶。同时记录这个元素在栈中的位置。
{
stack[0]++;
stack[stack[0]] = what;
zzz[what] = stack[0];
} void pop(int what) //把栈顶元素到what这个元素从栈中弹出来。栈指针指向what下面的元素
{ //这些弹出来的元素就属于同一个强连通分量
tot++; //递增编号
int tt = zzz[what] - 1; //改变栈指针的位置 先不赋值给stack[0],因为我们等下要用到stack[0]且zzz[what]会发生改变。
for (int i = zzz[what]; i <= stack[0]; i++) //把这些元素弹出
{
bianhao[stack[i]] = tot;//它们拥有同样的新编号。
zzz[stack[i]] = 0;//它们不在栈中了。所以改为0;
}
stack[0] = tt;//改变栈的指针。
} void tarjan(int x) //tarjan的递归程序
{
flag[x] = true; //进入之后把这个点标记为已经走过。
num++; //这是用来给dfn和low编号的
dfn[x] = low[x] = num; //df序
push(x);//把x这个元素加入到栈顶
int temp = first[x]; //获取它最后一次出现的位置
while (temp != 0) //如果还有出度
{
int y = en[temp]; //获取它的出度
if (w[x][y] == 0) //如果刚才已经走过这条边就不走了。
{
temp = next[temp];
continue;
}
w[x][y] = 0; //双向图。不能让他从x走到y又从y走到x。
w[y][x] = 0; //如果有重边的话要改成递减。
if (!flag[y]) //如果还没有访问过这个出度
{
tarjan(y); //则访问它
low[x] = min(low[x], low[y]); //同时尝试更改low[x];
}
else
if (zzz[y]>0) //如果访问过这个出度。就查看其是否在栈中
{
low[x] = min(low[x], dfn[y]); //如果在栈中就用其df序改变low[x];
}
temp = next[temp];//尝试找下一个出度。
}
if (low[x] == dfn[x]) //如果low[x]和x的df序相同。则弹出栈顶元素到x这个元素,表示
pop(x); //它们缩点后属于同一个点。
} void get_ans()
{
stack[0] = 0; //一开始栈为空。
memset(flag, false, sizeof(flag)); //一开始所有的节点都没有访问过。
for (int i = 1; i <= n; i++)
if (!flag[i]) //没有访问则访问它。
tarjan(i);
} int cmp(const bian &a, const bian &b) //则是为sort写的比较函数。
{
if (a.x < b.x) //x要递增
return 1;
if (a.x == b.x && a.y < b.y) //x相同则y也要递增。
return 1;
return 0;
} void output_ans() //输出答案
{
for (int i = 1; i <= m; i++) //对于每一条边判断其两个端点的新的编号是否相同。
{ //不同则为重要路径。
if (bianhao[a[i].x] != bianhao[a[i].y])
printf("%d %d\n", a[i].x, a[i].y);
}
} int main()
{
input_data();
get_ans();
std::sort(a + 1, a + 1 + m, cmp);
output_ans();
return 0;
}
【u209】轰炸的更多相关文章
- 短信轰炸PC版
前言 之前用过android版短信轰炸的apk,于是想反编apk查看源码找短信接口,做一个PC版本的,不料反编失败.后不了了之... 昨日逛论坛时无意中看到一个网站有此功能,打开一试究竟,效果可以,于 ...
- 洛谷 P1830 轰炸Ⅲ
P1830 轰炸Ⅲ 题目提供者wanglichao1121 标签模拟矩阵洛谷原创 难度普及/提高- 题目背景 一个大小为N*M的城市遭到了X次轰炸,每次都炸了一个每条边都与边界平行的矩形. 题目描述 ...
- javascript && php &&java 轰炸!!!
java && javascript && php 轰炸!!!恢复 1.javascript简介 *是基于对象和时间的驱动语言,应用于客户端. -----基于对象: * ...
- 遇到短信轰炸,别人换ip调你的短信接口怎么办
前端开发者很容易暴露自己的请求地址和参数,我们都知道,一个h5页面,按 F12 是可以看到页面的源码的,所以经常很多人会利用这一点恶意调取别人的接口. 我们公司出现了好多次短信接口被大量调用,导致一天 ...
- 小a的轰炸游戏 (差分)
我是看题解的! 这道题还是有很多细节,当然,是一道差分的好题! 题意:有2种飞机,一种是只炸上半菱形,一种是炸整个菱形.问所有区域内的所有格子的异或和. 思路:用前缀和思路: 这样遍历过去就完成了一次 ...
- 差分数组|小a的轰炸游戏-牛客317E
小a的轰炸游戏 题目链接:https://ac.nowcoder.com/acm/contest/317/E 思路 这题考查的是对差分数组原理和前缀和的理解. 四个数组分别记录朝着四个方向下放的个数 ...
- [动态差分+二维前缀和][小a的轰炸游戏]
链接:https://ac.nowcoder.com/acm/contest/317/E来源:牛客网 题目描述 小a正在玩一款即时战略游戏,现在他要用航空母舰对敌方阵地进行轰炸 地方阵地可以看做是n× ...
- 使用python进行短信轰炸
本文作者:i春秋作家——Hacker1ee 大家好,我是1ee(因为在作家群,就不加Hacker这个前缀了,怕被大佬打..) 刚加入i春秋作家组希望大家多多关照,也欢迎大家找我交流 今天我来讲讲我最近 ...
- 洛谷 P1142 轰炸
洛谷 P1142 轰炸 题目描述 “我该怎么办?”飞行员klux向你求助. 事实上,klux面对的是一个很简单的问题,但是他实在太菜了. klux要想轰炸某个区域内的一些地方,它们是位于平面上的一些点 ...
随机推荐
- 005 python 整数类型/字符串类型/列表类型/可变/不可变
可变/不可变类型 可变类型 ID不变的情况下,值改变,则称之为可变类型,如列表,字典 不可变类型 值改变,ID改变,则称之为不可变类型,如 整数 字符串,元组 整数类型 int 正整数 用途就是记录年 ...
- Android-ViewPager+Fragment数据更新问题
由于FragmentPagerAdapter内部存在缓存.因此调用notifyDataSetChanged()并不可以去更新Fragment的内容. 參考:http://www.devba.com/i ...
- C#程序集引入无效的解决方法
在项目类库中已经引用了相关了类库,生成解决方案也没问题,但是到了后置代码,通过using引用其他类库的时候,再生成解决方案或者生成单个类库,就会报“未能找到类型或命名空间“xxx"(是否缺少 ...
- Vue使用Promise自定义confirm确认框组件
使用Promise模拟浏览器确认框,可自定义标题,内容,按钮文字和类型 参数名 类型 说明 title String 标题 content String 内容 yesBtnText String 确认 ...
- 原生js大总结九
81.ES6的Symbol的作用是什么? ES6引入了一种新的原始数据类型Symbol,表示独一无二的值 82.ES6中字符串和数组新增了那些方法 字符串 1.字符串模板 ...
- 洛谷 P1510 精卫填海
洛谷 P1510 精卫填海 题目描述 [版权说明] 本题为改编题. [问题描述] 发鸠之山,其上多柘木.有鸟焉,其状如乌,文首,白喙,赤足,名曰精卫,其名自詨.是炎帝之少女,名曰女娃.女娃游于东海,溺 ...
- Java Web学习总结(12)——使用Session防止表单重复提交
在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...
- 洛谷 P2807 三角形计数
P2807 三角形计数 题目背景 三角形计数(triangle) 递推 题目描述 把大三角形的每条边n等分,将对应的等分点连接起来(连接线分别平行于三条边),这样一共会有多少三角形呢?编程来解决这个问 ...
- JS学习笔记 - 封装getPosition函数、一串跟着鼠标的div
function getPosition(ev) { var scrollTop = document.documentElement.scrollTop || document.body.scrol ...
- 使用BeautifulSoup爬取“0daydown”站点的信息(2)——字符编码问题解决
上篇中的程序实现了抓取0daydown最新的10页信息.输出是直接输出到控制台里面.再次改进代码时我准备把它们写入到一个TXT文档中.这是问题就出来了. 最初我的代码例如以下: #-*- coding ...