acdream1415(dij+优先队列+桥)
这题好坑,卡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
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
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
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+优先队列+桥)的更多相关文章
- L2-020. 功夫传人(dfs+vector 或者 邻接矩阵+dij+优先队列)
L2-020. 功夫传人 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 一门武功能否传承久远并被发扬光大,是要看缘分的.一般来 ...
- HDU6582 Path【优先队列优化最短路 + dinic最大流 == 最小割】
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6582 来源:2019 Multi-University Training Contest 1 题目大意 ...
- hdu3986 spfa+枚举
这题让我第一次感受到了什么叫做在绝望中A题.这题我总共交了18次,TLE不知道几次,WA也不知道几次. 这题不能用dijkstra,用这个我一直超时(我没试过dij+优先队列优化,好像优先队列优化后可 ...
- 洛谷题解 P2865 【[USACO06NOV]路障Roadblocks】
链接:https://www.luogu.org/problemnew/show/P2865 题目描述 Bessie has moved to a small farm and sometimes e ...
- codeforces 821 D. Okabe and City(最短路)
题目链接:http://codeforces.com/contest/821/problem/D 题意:n*m地图,有k个位置是点亮的,有4个移动方向,每次可以移动到相邻的点亮位置,每次站在初始被点亮 ...
- poj3013 邻接表+优先队列+Dij
把我坑到死的题 开始开题以为是全图连通是的最小值 ,以为是最小生成树,然后敲了发现不是,看了下别人的题意,然后懂了: 然后发现数据大,要用邻接表就去学了一下邻接表,然后又去学了下优先队列优化的dij: ...
- bzoj 1579: [Usaco2009 Feb]Revamping Trails 道路升级 优先队列+dij
1579: [Usaco2009 Feb]Revamping Trails 道路升级 Time Limit: 10 Sec Memory Limit: 64 MBSubmit: 1768 Solv ...
- dij的优先队列边表优化
dij的复杂度为v*v,通过优先队列优化后为e*logv. (第一次写,没有过多的测试,不保证对.只当是测试blog了!) #include<cstdio> #include<ios ...
- dij最短路优先队列堆的时候,加边
不能用全局数组d[u]>d[rhs.u]. 这样后面会修改d[u]值然而本来里面的点顺序不该修改,却被修改了. 应该用栈还存进去的临时变量,比如d>rhs.d. 优先队列重载小于号'< ...
随机推荐
- Android 6.0 超级简单的权限申请2 (Permission)
代码地址如下:http://www.demodashi.com/demo/13506.html 写在前面 上次写了一个权限申请的例子Android 6.0 超级简单的权限申请 (Permission) ...
- android实现超酷的腾讯视频首页和垂直水平网格瀑布流一揽子效果
代码地址如下:http://www.demodashi.com/demo/13381.html 先来一波demo截图 实现ListView.GridView.瀑布流 1.导入RecyclerView的 ...
- Linux命令-网络命令:mail
root用户发送邮件 mail wangyunpeng 给wangyunpeng发送邮件,wangyunpeng不在线也可以收到发送的邮件 wangyunpeng用户接收邮件 mail 接收邮件 he ...
- FZU 2087 统计树边【MST相关】
Problem 2087 统计树边 Accept: 212 Submit: 651 Time Limit: 1000 mSec Memory Limit : 32768 KB Prob ...
- JavaScript中使用JSON,即JS操作JSON总结
JSON(JavaScript Object Notation 对象标记) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式.同时,JSON是 JavaScript 原生 ...
- .Net并行编程高级教程(二)-- 任务并行
前面一篇提到例子都是数据并行,但这并不是并行化的唯一形式,在.Net4之前,必须要创建多个线程或者线程池来利用多核技术.现在只需要使用新的Task实例就可以通过更简单的代码解决命令式任务并行问题. 1 ...
- log4j DatePattern 解惑
og4j.appender.Root=org.apache.log4j.DailyRollingFileAppenderlog4j.appender.Root.File=../logs/bloglog ...
- Xcode5下使用纯代码构建简单的HelloWorld程序
转自:http://blog.csdn.net/developerxyf/article/details/12874935 新发布的Xcode5在使用模板创建工程的时候取消了以往是否要选择storyb ...
- datatables 相关文章
http://blog.csdn.net/zhu_xiao_yuan/article/details/51252300 datatables参数配置详解 http://blog.csdn.net/j ...
- C# MessageBox 消息对话框
在程序中,我们经常使用消息对话框给用户一定的信息提示,如在操作过程中遇到错误或程序异常,经常会使用这种方式给用于以提示.在C#中,MessageBox消息对话框位于System.Windows.For ...