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. 优先队列重载小于号'< ...
随机推荐
- 默认权限umask
什么是umask? 当我们登录系统之后创建一个文件总是有一个默认权限的,那么这个权限是怎么来的呢?这就是umask干的事情.umask设置了用户创建文件的默认 权限,它与chmod的效果刚好相反,um ...
- ConfigurationManager读取dll的配置文件
ConfigurationManager读取dll的配置文件 最近一个项目,需要发布dll给第三方使用,其中需要一些配置参数. 我们知道.NET的exe工程是自带的App.config文件的,编译之后 ...
- 基于mybatis-generator代码生成工具改(链式方法实体版)
概述 一直以来使用原生mybatis-generator的我发现有一个地方很不方便,即它生成的实体类的set方法返回值是void,而目前比较流行的则是链式set的写法,即set方法返回值不再是void ...
- MVC中Area的另一种用法
[摘要]本文只是为一行代码而分享 context.MapRoute("API", "api/{controller}/{action}", new { }, n ...
- unity, unity中GL.MultMatrix的一个超级bug
GL.MultMatrix与OpenGL固定管线的glMultMatrix函数行为并不一致,不是累乘,而是覆盖. 例如下面例子,本来预期是在(100,100)处画一个方块,而实际效果却是在(0,0)处 ...
- 深入Activity
此刻,你应该静下心来,在阅读中思考.在思考中进步,读完本篇文章的你一定会有不一样的收获,请让我们共同进步! 核心内容 1.Activity数据交换 2.Activity中的任务栈 3.Activity ...
- atitit.jQuery Validate验证框架详解与ati Validate 设计新特性
atitit.jQuery Validate验证框架详解与ati Validate 设计新特性 1. AtiValidate的目标1 2. 默的认校验规则1 2.1. 使用方式 1.metadata用 ...
- Linux之实用GDB技巧
一.引言 在Linux下开发,肯定少不了与gdb打交道,而gdb的命令又非常多,有些是不常用的但是特殊情况下却是必须的,因此记录在此,以便翻阅 二.基本命令 前面是命令全名,在不混淆的情况下,可以简写 ...
- 凑成整数x----二进制枚举
给n个数,给定x. 用这n个数求和凑成x,问有多少种凑法. #include<bits/stdc++.h> using namespace std; int main() { int n, ...
- PL/SQL Developer导入、导出表结构和表数据
在表的所有者不能改变的情况下,可以使用导入导出表结构和表数据的方法,将表移动到你想要的所有者下(注:特别是建立表的时候如果以sysdba的身份登录的话,所有表的所有者都为sys,此时会对你用c#访问数 ...