ACdream 1236 Burning Bridges 割边 + 去重边
题目就是求一副图的割边,然后对于那些有重复的边的,不能算做割边。
思路就是每次加入一条边的时候,判断这条边是否存在过,存在过的话,就把那条边设为inf,表示不能作为割边。于是有了这样的代码
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <cmath>
- #include <algorithm>
- using namespace std;
- #define inf (0x3f3f3f3f)
- typedef long long int LL;
- #include <iostream>
- #include <sstream>
- #include <vector>
- #include <set>
- #include <map>
- #include <queue>
- #include <string>
- const int maxn=+;
- struct data {
- int u,v,id;
- int next;
- } e[maxn*];
- int first[+];
- int num;//??????
- bool isok (int u,int v) {
- //???u????????????
- for (int i=first[u]; i; i=e[i].next) {
- if (e[i].v==v) {
- e[i].id=inf;
- return false;
- }
- }
- return true;
- }
- void add (int u,int v,int id) {
- if (!isok(u,v)) return ;//???????????????
- ++num;
- e[num].u=u;
- e[num].v=v;
- e[num].id=id;
- e[num].next=first[u];
- first[u]=num;
- return ;
- }
- int DFN[+];//???????
- int low[+];//????????
- int when;//?????????
- int root;
- set<int>pr;
- void dfs (int cur,int father) {
- ++when;
- DFN[cur]=when;
- low[cur]=when;
- for (int i=first[cur]; i; i=e[i].next) {
- int v=e[i].v;//cur????v???
- if (!DFN[v]) { //??????
- dfs(v,cur);
- low[cur]=min(low[cur],low[v]);
- if (low[v]>DFN[cur]&&e[i].id!=inf) {
- pr.insert(e[i].id);
- }
- } else if(v!=father) {
- low[cur]=min(low[cur],DFN[v]);
- }
- }
- return ;
- }
- void init () {
- pr.clear();
- memset(DFN,,sizeof(DFN));
- memset(low,,sizeof(low));
- memset (first,,sizeof first);
- when=;
- num=;
- return ;
- }
- int n,m;
- void work () {
- init ();
- for (int i=; i<=m; i++) {
- int u,v;
- scanf ("%d%d",&u,&v);
- add(u,v,i);
- add(v,u,i);
- }
- root=;//????
- dfs(,root);
- printf ("%d\n",pr.size());
- for (set<int>::iterator it= pr.begin(); it!=pr.end(); ++it) {
- printf ("%d ",*it);
- }
- printf ("\n");
- return ;
- }
- int main () {
- while (scanf ("%d%d",&n,&m)!=EOF) work ();
- return ;
- }
240ms过的。但是应该会有些坑爹的图,卡到它TLE的。
所以这个方法不行
考虑去重,做到O(m)
用used[v] = u表示u--v这样有一条边了。
建立完整张图后,遍历一次,如果重复的话,就去掉就行了。used数组不用清空,因为值u肯定是不同的。
坑就是出现了两次,才能判断第二条边重复了。那么第一条边怎么设置为inf呢?
方法就是用一个数组togo[v] = j表示,当前顶点v的上一条边是j。去重即可。
压缩时间为44ms
- #include <cstdio>
- #include <cstdlib>
- #include <cstring>
- #include <cmath>
- #include <algorithm>
- using namespace std;
- #define inf (0x3f3f3f3f)
- typedef long long int LL;
- #include <iostream>
- #include <sstream>
- #include <vector>
- #include <set>
- #include <map>
- #include <queue>
- #include <string>
- const int maxn=+;
- struct data {
- int u,v,id;
- int next;
- } e[maxn*];
- int first[+];
- int num;//用到第几条边
- bool isok (int u,int v) {
- //问一下u顶点所有边能不能去这个点
- for (int i=first[u]; i; i=e[i].next) {
- if (e[i].v==v) {
- e[i].id=inf;
- return false;
- }
- }
- return true;
- }
- void add (int u,int v,int id) {
- // if (!isok(u,v)) return ;//判断是否有重复的边,绝对不是桥
- ++num;
- e[num].u=u;
- e[num].v=v;
- e[num].id=id;
- e[num].next=first[u];
- first[u]=num;
- return ;
- }
- int DFN[+];//第几个被访问到
- int low[+];//最厉害能访问到谁
- int used[ + ];
- int togo[ + ];
- int when;//什么时候被访问到的
- int root;
- set<int>pr;
- void dfs (int cur,int father) {
- ++when;
- DFN[cur]=when;
- low[cur]=when;
- for (int i=first[cur]; i; i=e[i].next) {
- int v=e[i].v;//cur是爸爸,v是儿子
- if (!DFN[v]) { //没访问过的话
- dfs(v,cur);
- low[cur]=min(low[cur],low[v]);
- if (low[v]>DFN[cur]&&e[i].id!=inf) {
- pr.insert(e[i].id);
- }
- } else if(v!=father) {
- low[cur]=min(low[cur],DFN[v]);
- }
- }
- return ;
- }
- void init () {
- memset(togo, , sizeof togo);
- memset(used, , sizeof used);
- pr.clear();
- memset(DFN,,sizeof(DFN));
- memset(low,,sizeof(low));
- memset (first,,sizeof first);
- when=;
- num=;
- return ;
- }
- int n,m;
- void work () {
- init ();
- for (int i=; i<=m; i++) {
- int u,v;
- scanf ("%d%d",&u,&v);
- add(u,v,i);
- add(v,u,i);
- }
- for (int i = ; i <= n; ++i) {
- // memset(used, 0, sizeof used);
- for (int j = first[i]; j; j = e[j].next) {
- if (used[e[j].v] == e[j].u) {
- e[j].id = inf;
- e[togo[e[j].v]].id = inf;
- }
- used[e[j].v] = e[j].u;
- togo[e[j].v] = j;
- }
- }
- root=;//从根节点
- dfs(,root);
- printf ("%d\n",pr.size());
- for (set<int>::iterator it= pr.begin(); it!=pr.end(); ++it) {
- printf ("%d ",*it);
- }
- printf ("\n");
- return ;
- }
- int main () {
- #ifdef local
- freopen("data.txt", "r", stdin);
- #endif
- while (scanf ("%d%d",&n,&m)!=EOF) work ();
- return ;
- }
ACdream 1236 Burning Bridges 割边 + 去重边的更多相关文章
- ZOJ 2588 Burning Bridges 割边(处理重边)
<题目链接> 题目大意: 给定一个无向图,让你尽可能的删边,但是删边之后,仍然需要保证图的连通性,输出那些不能被删除的边. 解题分析: 就是无向图求桥的题目,主要是提高一下处理重边的姿势. ...
- zoj 2588 Burning Bridges(割边/桥)
题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1588 题意:Ferry王国有n个岛,m座桥,每个岛都可以互达,现在要 ...
- ZOJ 2588 Burning Bridges(求含重边的无向连通图的割边) - from lanshui_Yang
Burning Bridges Time Limit: 5 Seconds Memory Limit: 32768 KB Ferry Kingdom is a nice little country ...
- Burning Bridges 求tarjan求割边
Burning Bridges 给出含有n个顶点和m条边的连通无向图,求出所有割边的序号. 1 #include <cstdio> 2 #include <cstring> 3 ...
- ZOJ 2588 Burning Bridges(无向连通图求割边)
题目地址:ZOJ 2588 由于数组开小了而TLE了..这题就是一个求无向连通图最小割边.仅仅要推断dfn[u]是否<low[v],由于low指的当前所能回到的祖先的最小标号,增加low[v]大 ...
- zoj——2588 Burning Bridges
Burning Bridges Time Limit: 5 Seconds Memory Limit: 32768 KB Ferry Kingdom is a nice little cou ...
- zoj 2588 Burning Bridges【双连通分量求桥输出桥的编号】
Burning Bridges Time Limit: 5 Seconds Memory Limit: 32768 KB Ferry Kingdom is a nice little cou ...
- xtu summer individual 5 E - Burning Bridges
Burning Bridges Time Limit: 5000ms Memory Limit: 32768KB This problem will be judged on ZJU. Origina ...
- ZOJ 2588 Burning Bridges(求桥的数量,邻接表)
题目地址:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2588 Burning Bridges Time Limit: 5 ...
随机推荐
- 使用tftp给ARM下载程序
使用tftp给ARM下载程序 1.开发板和主机能够ping的通 前提:要把计算机的防火墙关了,不然就会出现下面这种情况 如果电脑连接的无线网,那么设置本地连接的ip设置为固定ip.Ip地址和开发的ip ...
- JSP介绍(3)---JSP表单处理
GET方法: GET方法将请求的编码信息添加在网址后面,网址与编码信息通过"?"号分隔.如下所示: http://www.runoob.com/hello?key1=value1& ...
- javascript面向对象的测试实例
- 仿QQ底部切换(Fragment + Radio)
第一步: activity_main.xml 布局文件 <RelativeLayout xmlns:android="http://schemas.android.com/apk/ ...
- [poj3264]rmq算法学习(ST表)
解题关键:rmq模板题,可以用st表,亦可用线段树等数据结构 log10和log2都可,这里用到了对数的换底公式 类似于区间dp,用到了倍增的思想 $F[i][j] = \min (F[i][j - ...
- 【总结整理】JQuery小技巧
var item=$("#content").find(".item");//效率最高 var item=$("#content .item" ...
- Umbraco Examine 实现Fuzzy search
在Umbraco examine search项目开发中,有一个需求, 就是intercom 和 intercoms需要返回同样的结果 也就是说 搜索intercom 时, 能返回包含intercom ...
- HTML5程序开发范例宝典 完整版 (韩旭等著) 中文pdf扫描版
HTML5程序开发范例宝典紧密围绕编程者在编程中遇到的实际问题和开发中应该掌握的技术,全面介绍了利用HTML进行程序开发的各方面技术和技巧.全书共16章,内容包括HTML网页布局.HTML基本元素.H ...
- SQL中的union,except,intersect用法
限制:所有查询中的列数和列的数序必须相同 union all:完全整合两个结果集查出所有数据 union:查出两个表的数据并且去除重复的数据 except:去重之后只会保留第一个表中的数据,查询a表在 ...
- ProtoBuf练习(六)
JSON类型 工程目录结构 $ ls proto/ proto文件 $ cat proto/style.proto syntax = "proto3"; import " ...