题目大意:
  给定一个$n(n\leq40000)$个点$m(m\leq100000)$条边的有向图,求从$1$出发回到$1$的不经过重复结点的最短路。

思路:
  首先Dijkstra求出从1出发到每个结点$i$的单源最短路$dis[i]$及经过的第一个结点$first[i]$。
  考虑重构图,将起点与终点区分开来,新建结点$n+1$表示终点。
  枚举原图中的每一条边$(x,y,w)$,表示从$x$到$y$边权为$w$。
  若$x=1,first[y]\ne y$,在新图中保留这条边;
  若$y=1,first[x]\ne x$,说明存在一条从$1$沿最短路到$x$再到$1$的合法路径,在新图中连边$(1,n+1,w)$;
  若$y=1,first[x]=x$,在新图中保留这条边;
  若$x\ne1,y\ne1,first[x]\ne first[y]$,说明存在一条从$1$沿最短路到$x$再到$y$再沿最短路到$1$的合法路径,连边$(1,y,dis[x]+w)$;
  若$x\ne1,y\ne1,first[x]=first[y]$,在新图中保留这条边。
  最后再求一遍从$1$到$n+1$的最短路即可。

 #include<list>
#include<cstdio>
#include<cctype>
#include<climits>
#include<functional>
#include<ext/pb_ds/priority_queue.hpp>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const int N=;
typedef std::pair<int,int> Edge;
typedef std::list<Edge> List;
typedef std::pair<int,int> Vertex;
typedef __gnu_pbds::priority_queue<Vertex,std::greater<Vertex> > Heap;
int n,dis[N],first[N];
List e[N];
inline void add_edge(const int &u,const int &v,const int &w) {
e[u].push_front((Edge){v,w});
}
void dijkstra() {
static Heap q;
static Heap::point_iterator p[N];
for(register int i=;i<=n;i++) {
p[i]=q.push((Vertex){dis[i]=i==?:INT_MAX,i});
}
while(!q.empty()) {
const int &x=q.top().second;
for(register List::iterator i=e[x].begin();i!=e[x].end();i++) {
const int &y=i->first,&w=i->second;
if(dis[x]+w<dis[y]) {
first[y]=x==?y:first[x];
q.modify(p[y],(Vertex){dis[y]=dis[x]+w,y});
}
}
q.pop();
}
}
void rebuild() {
n++;
for(register int x=;x<=n;x++) {
for(register List::iterator i=e[x].begin();i!=e[x].end();e[x].erase(i++)) {
const int &y=i->first,&w=i->second;
if(x==&&first[y]!=y) add_edge(,y,w);
if(y==) first[x]==x?add_edge(x,n,w):add_edge(,n,dis[x]+w);
if(x!=&&y!=) first[x]==first[y]?add_edge(x,y,w):add_edge(,y,dis[x]+w);
}
}
}
int main() {
n=getint();
for(register int m=getint();m;m--) {
const int u=getint(),v=getint();
add_edge(u,v,getint());
add_edge(v,u,getint());
}
dijkstra();
rebuild();
dijkstra();
printf("%d\n",dis[n]==INT_MAX?-:dis[n]);
return ;
}

最新文章

  1. HTML5属性--(capture=&quot;camera&quot;) 上传照片或者打开手机相机
  2. windows环境下无法引用全局安装的模块问题
  3. 如何让ListView的item不可点击
  4. oc 正则图片&lt;img /&gt; 标签
  5. Android之BroadcastReceiver 监听系统广播
  6. 利用Fragment创建动态UI 之 Fragment之间的通信
  7. 数据库创建&amp;数据表创建
  8. Java连接MySQL中文乱码处理【转载】
  9. 剑指offer-面试题12.打印1到最大的n位数
  10. POJ 1077 HDU 1043 Eight (IDA*)
  11. bresenham算法的FPGA的实现1
  12. mysql联合索引的应用
  13. 读书笔记 effective c++ Item 35 考虑虚函数的替代者
  14. Django_中国化
  15. 【ASP.NET Core】解决“The required antiforgery cookie &quot;xxx&quot; is not present”的错误
  16. Linux显示服务器完整的状态信息
  17. Linux(Ubuntu)安装libpcap
  18. maya cmds pymel undoInfo chunk 撤销束
  19. 安卓开发_浅谈AsyncTask
  20. Python 学习 第七篇:函数1(定义、调用和变量的作用域)

热门文章

  1. day06_07 字典操作02
  2. Linux(Ubuntu 命令大全)
  3. 易语言.开源(绝地求生多功能盒子)类似LOL盒子
  4. HDU 4741 Save Labman No.004 ( 三维计算几何 空间异面直线距离 )
  5. python鉴黄程序
  6. PHP7 深入理解
  7. idea中新建的web项目不能新建servlet
  8. sql server 中使用 LIKE 语句 SqlParameter 使用
  9. 关于ECDSA/ECC(密钥加密传输)和ECDSA/ECDH(密钥磋商)
  10. [codeforces] 585D Lizard Era: Beginning || 双向dfs