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. 优先队列重载小于号'< ...
随机推荐
- Python之基础数学知识
一.线性代数 1.求转置 import numpy m = numpy.mat([[1, 2], [3, 4]]) print("Matrix.Transpose:") print ...
- Python 射线法判断一个点坐标是否在一个坐标区域内
class Point: lng = '' lat = '' def __init__(self, lng, lat): self.lng = lng self.lat = lat # 求外包矩形 d ...
- 数据库出错提示Duplicate entry * for key *的解决方法
错误编号:1062 错误提示: 查询语句错误] ERR: Duplicate entry ' for key 'PRIMARY' SQL: ' PHP: misc.php: ; IP 问题分析: 向唯 ...
- 解决eclipse偶尔无视breakpoint的行为
一般是如果你使用了T[]这样的参数列表,也就是generic array作为参数,你就算给函数打了断点,有时也会被eclipse无视 比如如下代码,你在调试main的时候,eclipse就会把doPa ...
- Nmap笔记本
nmap -vv 192.168.1.100 -p1-65535 跑1-65535的端口并且设置对结果的详细输出 nmap -vv 192.168.1.1/8 -p 1433 --open 跑开放14 ...
- web.py使用要点
这几天有一个构建restful services的需求,我采用了web.py,之前并没有使用过,但在使用中确实给我带来了很多惊喜.当然,最大的惊喜就是简单,方便.之前开发restful服务的时候,采用 ...
- wget命令 -c断点续传
wget -O wordpress.zip http://www.linuxde.net/download.aspx?id=1080 下载文件在指定位置并进行重命名 -O file - ...
- java部署ubuntu后中文显示问号问题
1.首先先回忆自身项目的编码格式,即在本地进行编码时使用的编码格式.UTF-82.检测tomcat的设置问题,在web.xml和server中的设置:server.xml中: <Connecto ...
- 常见sql 写法总结
关于如何获取1对多数据中最大条数据的写法 例子: LEFT JOIN ( SELECT * FROM table AS n1 WHERE n1.ID IN ( SELECT MAX(id) FROM ...
- 【BZOJ】3299: [USACO2011 Open]Corn Maze玉米迷宫(bfs)
http://www.lydsy.com/JudgeOnline/problem.php?id=3299 映射一下传送门即可.. #include <cstdio> #include &l ...