这题好坑,卡SPFA。。。

无奈只能用dij+优先队列了。 因为好久没有写过代码了,所以今天写dij时候突然觉得复杂度不对,dij+优先队列的复杂度是(n+m)logn,这种复杂度对于稠密图是非常慢!,而且还有超内存的可能(最坏情况要把n*n个点都存进优先队列),与我以前记得复杂度是nlogn不一样。。。 瞬间吓尿。

其实事实确实是这样,在采用斐波那契堆+dij时,斐波那契堆是插入复杂度为O(1),所以复杂度为nlogn+m,而普通我们用的STL种的priority_queue插入查询复杂度都是logn,所以总的复杂度为(n+m)logn.

所以,dij+优先队列虽然方便好写,但只适用用稀疏图,也就是m小的时候。

最后关于这题的思路,求一次从1开始到其他所有点的最短距离diss[i],再求一次从n开始到其他所有点的最短距离dist[i],然后如果边 <u,v>w 满足diss[u]+w+dist[v]=min(其中min是1到n的最短距离)说明这条边,绝对在一条最短路线中。 这样把所有这样的边找出来,并重新构图,那么只要找出这个图中的桥,并且满足1,n分别在桥的两端。

Important Roads

Special JudgeTime Limit: 20000/10000MS (Java/Others)Memory Limit: 128000/64000KB (Java/Others)

Problem Description

The city where Georgie lives has n junctions some of which are connected by bidirectional roads.
      Every day Georgie drives from his home to work and back. But the roads in the city where Georgie lives are very bad, so they are very often closed for repair. Georgie noticed that when some roads are closed he still can get from home to work in the same time as if all roads were available.

But there are such roads that if they are closed for repair the time Georgie needs to get from home to work increases, and sometimes Georgie even cannot get to work by a car any more. Georgie calls such roads important.
      Help Georgie to find all important roads in the city.

Input

The first line of the input file contains n and m — the number of junctions and roads in the city where Georgie lives, respectively (2 ≤ n ≤ 20 000, 1 ≤ m ≤ 100 000). Georgie lives at the junction 1 and works at the junction n.

The following m lines contain information about roads. Each road is specified by the junctions it connects and the time Georgie needs to drive along it. The time to drive along the road is positive and doesn’t exceed 100 000. There can be several roads between a pair of junctions, but no road connects a junction to itself. It is guaranteed that if all roads are available, Georgie can get from home to work.

Output

      Output l — the number of important roads — at the first line of the output file. The second line must contain l numbers, the numbers of important roads. Roads are numbered from 1 to m as they are given in the input file.

Sample Input

6 7
1 2 1
2 3 1
2 5 3
1 3 2
3 5 1
2 4 1
5 6 2

Sample Output

2
5 7

Source

Andrew Stankevich Contest 22

Manager

 #include <iostream>
#include <stdio.h>
#include <string.h>
#include <string>
#include <algorithm>
#include <stdlib.h>
#include <queue>
using namespace std;
#define M 100100
#define N 20020
#define INF 0x3fffffffff int n,m;
struct node
{
int from,to,next,w,id;
}edge[*M]; struct node1
{
long long w;
int id;
bool operator < (const node1 t)const
{
return t.w<w;
}
}; int pre[N],cnt;
long long int diss[N],dist[N];
int que[M+];//用循环队列怎么样
int ans,save[M];
//然后就是找桥了 priority_queue<node1> pque; int len[N],mark[M];
int index1; void add_edge(int u,int v,int w,int id)
{
edge[cnt].from=u;
edge[cnt].to=v;
edge[cnt].w=w;
edge[cnt].id=id;
edge[cnt].next=pre[u];
pre[u]=cnt++;
} void dij(long long int dis[N],int s)
{
memset(mark,,sizeof(mark));
while(pque.size()!=) pque.pop(); for(int i=;i<=n;i++)
dis[i]=INF; dis[s]=;
node1 fi;
fi.id=s;
fi.w=;
pque.push(fi);
//我就说, 用优先队列优化,对于稠密图基本没意义
node1 nwnode,cur;
while(pque.size()!=)
{
cur = pque.top();
pque.pop();
if(mark[cur.id]==) continue;
int u=cur.id;
mark[u]=;
for(int p=pre[u];p!=-;p=edge[p].next)
{
int v=edge[p].to;
if(mark[v]==) continue;
if(dis[v]>cur.w+edge[p].w)
{
dis[v]=cur.w+edge[p].w;
nwnode.id=v;
nwnode.w=dis[v];
pque.push(nwnode);
}
}
}
} void spfa(long long int dis[N],int s,int t)
{
//SPFA都忘记怎么写了
memset(mark,,sizeof(mark));
for(int i=;i<=n;i++)
{
dis[i]=INF;
} int qf=,qd=;
que[qf]=s;
qf++; dis[s]=;
mark[s]=; while(qf!=qd)//作为一个循环队列,
{
int cur=que[qd];
qd=(qd+)%M;
mark[cur]=;
for(int p=pre[cur];p!=-;p=edge[p].next)
{
int v = edge[p].to;
if( dis[v]>dis[cur] + edge[p].w )
{
dis[v]=dis[cur]+edge[p].w;
if(mark[v]==)
{
que[qf]=v;
qf=(qf+)%M;
mark[v]=;
}
}
}
}
} void dfs(int s)
{
//len[s]==-1表示没来过 len[s]=index1++;
int tmp = len[s];
for(int p=pre[s];p!=-;p=edge[p].next)
{
int v=edge[p].to;
if( mark[edge[p].id]== ) continue; if(len[v]==-)
{
mark[edge[p].id]=;//把这条边标记了
dfs(v);
tmp=min(tmp,len[v]);
if(len[v]>len[s])//这个就是桥
{
if(len[n]!=-)
{
if(len[]<=len[s]&&len[n]>=len[v])
{
save[ans++]=edge[p].id;
}
}
}
}//无向图的桥怎么求。。。,忘光了。
else
{
tmp=min(tmp,len[v]);
}
} len[s]=tmp;
} int main()
{
scanf("%d%d",&n,&m);
cnt=;
memset(pre,-,sizeof(pre)); for(int i=;i<=m;i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
add_edge(x,y,w,i);
add_edge(y,x,w,i);
} //卡SPFA???
//去你妹的 //spfa(diss,1,n);
//spfa(dist,n,1); dij(diss,);
dij(dist,n); long long int mi=diss[n]; //最短距离
int tcnt = cnt; cnt=;
memset(pre,-,sizeof(pre)); for(int i=;i<tcnt;i+=)
{
int x,y,w,id;
x=edge[i].from;
y=edge[i].to;
w=edge[i].w;
id=edge[i].id;
if( diss[x]+dist[y]+w ==mi || dist[x] + diss[y]+w==mi )
{
add_edge(x,y,w,id);
add_edge(y,x,w,id);
}
}
//构建了一个由所有可能最短路边构成的图
memset(mark,,sizeof(mark)); //感觉要用来记录边比较好
memset(len,-,sizeof(len));
index1=;
ans = ; dfs();
printf("%d\n",ans);
if(ans!=)
{
for(int i=;i<ans-;i++)
printf("%d ",save[i]);
printf("%d\n",save[ans-]);
}
return ;
}

acdream1415(dij+优先队列+桥)的更多相关文章

  1. L2-020. 功夫传人(dfs+vector 或者 邻接矩阵+dij+优先队列)

    L2-020. 功夫传人 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 一门武功能否传承久远并被发扬光大,是要看缘分的.一般来 ...

  2. HDU6582 Path【优先队列优化最短路 + dinic最大流 == 最小割】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6582 来源:2019 Multi-University Training Contest 1 题目大意 ...

  3. hdu3986 spfa+枚举

    这题让我第一次感受到了什么叫做在绝望中A题.这题我总共交了18次,TLE不知道几次,WA也不知道几次. 这题不能用dijkstra,用这个我一直超时(我没试过dij+优先队列优化,好像优先队列优化后可 ...

  4. 洛谷题解 P2865 【[USACO06NOV]路障Roadblocks】

    链接:https://www.luogu.org/problemnew/show/P2865 题目描述 Bessie has moved to a small farm and sometimes e ...

  5. codeforces 821 D. Okabe and City(最短路)

    题目链接:http://codeforces.com/contest/821/problem/D 题意:n*m地图,有k个位置是点亮的,有4个移动方向,每次可以移动到相邻的点亮位置,每次站在初始被点亮 ...

  6. poj3013 邻接表+优先队列+Dij

    把我坑到死的题 开始开题以为是全图连通是的最小值 ,以为是最小生成树,然后敲了发现不是,看了下别人的题意,然后懂了: 然后发现数据大,要用邻接表就去学了一下邻接表,然后又去学了下优先队列优化的dij: ...

  7. bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 优先队列+dij

    1579: [Usaco2009 Feb]Revamping Trails 道路升级 Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1768  Solv ...

  8. dij的优先队列边表优化

    dij的复杂度为v*v,通过优先队列优化后为e*logv. (第一次写,没有过多的测试,不保证对.只当是测试blog了!) #include<cstdio> #include<ios ...

  9. dij最短路优先队列堆的时候,加边

    不能用全局数组d[u]>d[rhs.u]. 这样后面会修改d[u]值然而本来里面的点顺序不该修改,却被修改了. 应该用栈还存进去的临时变量,比如d>rhs.d. 优先队列重载小于号'< ...

随机推荐

  1. 基于redis的简易分布式爬虫框架

    代码地址如下:http://www.demodashi.com/demo/13338.html 开发环境 Python 3.6 Requests Redis 3.2.100 Pycharm(非必需,但 ...

  2. 获取SQL Server的安装时间

    近期安装SQL Server 2014时.还没有正式的License,仅仅能试用3个月.想知道什么时候到期,就要知道SQL Server 2014是什么时候安装的.假设你没有特意记录安装日期(实际大部 ...

  3. 使用cros实现跨域请求

    直接上代码 后端 this.Response.Headers.Add("Access-Control-Allow-Origin","*"); 响应流里添加一个h ...

  4. Kafka 快速起步

    Kafka 快速起步 原创 2017-01-05 杜亦舒 性能与架构 性能与架构 性能与架构 微信号 yogoup 功能介绍 网站性能提升与架构设计 主要内容:1. kafka 安装.启动2. 消息的 ...

  5. Atitit.判断汉字的编码 regedit 注册表里面的reg_sz

    Atitit.判断汉字的编码 regedit 注册表里面的reg_sz 1. 可以判断出是unicode编码1 2. 有下面分割ucs2 大头小偷编码1 3. 使用小偷编码测试1 4. 注册表里面的r ...

  6. gpg: symbol lookup error

    今天使用sudo apt-get 安装包的时候,出现gpg错误,如下: gpg: symbol lookup error: /usr/local/lib/libreadline.so.6: undef ...

  7. python学习之logging模块

    Logger.setLevel(level) 设置记录器的级别为level.低于该级别的信息将被忽略. 记录器默认级别为NOTSET.如果记录器是根记录器,则默认将记录所有信息: 如果是一个非根记录器 ...

  8. 【转】Apache虚拟主机的配置和泛解析域名的绑定

    基于IP地址的虚拟主机配置 Listen 80 DocumentRoot /www/example1 ServerName www.example1.com DocumentRoot /www/exa ...

  9. C/C++开发平时用的自定义debug函数

    一.无颜色版 一.自定义printf #include <stdio.h> #ifdef MYDEBUG #define DEBUG(arg...) {\ printf("[de ...

  10. SQL练习题汇总(Sqlserver和Mysql版本)

    所需表及数据执行脚本: CREATE TABLE STUDENT (SNO ) NOT NULL, SNAME ) NOT NULL, SSEX ) NOT NULL, SBIRTHDAY DATET ...