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. 【SSH高速进阶】——struts2简单的实例

    近期刚刚入门struts2.这里做一个简单的struts2实例来跟大家一起学习一下. 本例实现最简单的登陆,仅包括两个页面:login.jsp 用来输入username与password:succes ...

  2. 导入数据库工具有关的oracle sql操作

    alter table TAB_user add (personal varchar2(30) default '用户名' not null);alter table TAB_user modify ...

  3. android-铃声的设置与播放

    在android系统中,不同铃声存放的铃声路径: /system/media/audio/ringtones 来电铃声 /system/media/audio/notifications 短信通知铃声 ...

  4. leetcode笔记:Word Break

    一. 题目描写叙述 Given a string s and a dictionary of words dict, determine if s can be segmented into a sp ...

  5. 使用mingw制作dll文件

    使用mingw制作dll文件 安装mingw 准备math.c文件 //math.c #include<stdio.h> int add(int a,int b){ return a+b; ...

  6. HibernateCRUD基础框架(3)-简单的和较为复杂的标准的CRUD API

    优点:简单的和基础的CRUD功能可以很快实现,可以说是比较的"标准化".维护起来也很容易. 缺点:性能没有保障.不支持特别复杂的CRUD. 可以适用的场景:小型Web项目 1.Cr ...

  7. C#DateTime与Unix时间戳的转换

    /// <summary> /// Unix时间戳转为C#格式时间 /// </summary> /// <param name="timeStamp" ...

  8. php 获取数组第一个key 第一个键值对 等等

    PHP 获取数组中的第一个元素或最后一个元素的值或者键值可以使用 PHP 自带的数组函数. PHP 获取数组中的第一个元素的值或者键值所使用的函数: current() - 返回数组中当前元素值(即: ...

  9. 【SPOJ 694】Distinct Substrings

    [链接]h在这里写链接 [题意]     给你一个长度最多为1000的字符串     让你求出一个数x,这个x=这个字符串的不同子串个数; [题解]     后缀数组题.     把原串复制一份,加在 ...

  10. AE IColor.rgb 的计算

    原文 AE IColor.rgb 的计算方法 IColor的rgb属性 是通过对应 的红 绿 蓝 值计算出来的,那么AE的内部计算方法是什么呢? 其实就是一个256进制的BGR数.下面是转换算法: / ...