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】轰炸的更多相关文章

  1. 短信轰炸PC版

    前言 之前用过android版短信轰炸的apk,于是想反编apk查看源码找短信接口,做一个PC版本的,不料反编失败.后不了了之... 昨日逛论坛时无意中看到一个网站有此功能,打开一试究竟,效果可以,于 ...

  2. 洛谷 P1830 轰炸Ⅲ

    P1830 轰炸Ⅲ 题目提供者wanglichao1121 标签模拟矩阵洛谷原创 难度普及/提高- 题目背景 一个大小为N*M的城市遭到了X次轰炸,每次都炸了一个每条边都与边界平行的矩形. 题目描述 ...

  3. javascript && php &&java 轰炸!!!

    java && javascript && php 轰炸!!!恢复 1.javascript简介 *是基于对象和时间的驱动语言,应用于客户端. -----基于对象: * ...

  4. 遇到短信轰炸,别人换ip调你的短信接口怎么办

    前端开发者很容易暴露自己的请求地址和参数,我们都知道,一个h5页面,按 F12 是可以看到页面的源码的,所以经常很多人会利用这一点恶意调取别人的接口. 我们公司出现了好多次短信接口被大量调用,导致一天 ...

  5. 小a的轰炸游戏 (差分)

    我是看题解的! 这道题还是有很多细节,当然,是一道差分的好题! 题意:有2种飞机,一种是只炸上半菱形,一种是炸整个菱形.问所有区域内的所有格子的异或和. 思路:用前缀和思路: 这样遍历过去就完成了一次 ...

  6. 差分数组|小a的轰炸游戏-牛客317E

    小a的轰炸游戏 题目链接:https://ac.nowcoder.com/acm/contest/317/E 思路  这题考查的是对差分数组原理和前缀和的理解. 四个数组分别记录朝着四个方向下放的个数 ...

  7. [动态差分+二维前缀和][小a的轰炸游戏]

    链接:https://ac.nowcoder.com/acm/contest/317/E来源:牛客网 题目描述 小a正在玩一款即时战略游戏,现在他要用航空母舰对敌方阵地进行轰炸 地方阵地可以看做是n× ...

  8. 使用python进行短信轰炸

    本文作者:i春秋作家——Hacker1ee 大家好,我是1ee(因为在作家群,就不加Hacker这个前缀了,怕被大佬打..) 刚加入i春秋作家组希望大家多多关照,也欢迎大家找我交流 今天我来讲讲我最近 ...

  9. 洛谷 P1142 轰炸

    洛谷 P1142 轰炸 题目描述 “我该怎么办?”飞行员klux向你求助. 事实上,klux面对的是一个很简单的问题,但是他实在太菜了. klux要想轰炸某个区域内的一些地方,它们是位于平面上的一些点 ...

随机推荐

  1. 洛谷P1876 开灯

    题目背景 该题的题目是不是感到很眼熟呢? 事实上,如果你懂的方法,该题的代码简直不能再短. 但是如果你不懂得呢?那...(自己去想) 题目描述 首先所有的灯都是关的(注意是关!),编号为1的人走过来, ...

  2. 利用formdata对象上传文件时,需要添加的参数

    function doUpload() { var formData = new FormData($( "#uploadForm" )[0]); $.ajax({ url: 'h ...

  3. JAVE 视音频转码

    http://blog.csdn.net/qllinhongyu/article/details/29817297

  4. 《TCP/IP具体解释卷2:实现》笔记--协议控制块

    协议层使用协议控制块(PCB)存放各UDP和TCP插口所要求的多个信息片.Internet协议维护Internet协议控制块 (internet protocol control block)和TCP ...

  5. Lucy_Hedgehog techniques

    在project euler 的第\(10\)题的 \(forum\) 中 Lucy Hedgehog 提到的这种方法. 求 \(n\) 以内素数个数以及求 \(n\) 以内素数和的算法. 定义\(S ...

  6. POJ 1064 Cable master 浮点数二分

    http://poj.org/problem?id=1064 题目大意: 有N条绳子,他们的长度分别为Li,如果从它们中切割出k条长度相同的绳子的话,这K条绳子每条能有多长? 思路: 二分,设答案为m ...

  7. loadrunne-- Analysis 分析器

    本文转自:https://www.cnblogs.com/Chilam007/p/6445165.html Analysis简介 分析器就是对测试结果数据进行分析的组件,它是LR三大组件之一,保存着大 ...

  8. .NetCore微服务Surging新手傻瓜式 入门教程 学习日志---结构简介(二)

    原文:.NetCore微服务Surging新手傻瓜式 入门教程 学习日志---结构简介(二) 先上项目解决方案图: 以上可以看出项目结构可以划分为4大块,1是surging的核心底层,2,3,4都可以 ...

  9. 微服务实战(六):选择微服务部署策略 - DockOne.io

    原文:微服务实战(六):选择微服务部署策略 - DockOne.io [编者的话]这篇博客是用微服务建应用的第六篇,第一篇介绍了微服务架构模板,并且讨论了使用微服务的优缺点.随后的文章讨论了微服务不同 ...

  10. c++11 多线程 -- 基本使用

    c++11 多线程 – 基本使用 前言:这篇文章仅针对没有使用过c++11线程库的童鞋来高速入门,也是自己的一个简单记录,内容比較基础. 1.线程的基本使用 2.相互排斥量 3.条件变量 4.原子变量 ...