试题描述
输入数据给出一个有 N 个节点,M 条边的带权有向图。要求你写一个程序,判断这个有向图中是否存在负权回路。如果从一个点沿着某条路径出发,又回到了自己,而且所经过的边上的权和小于 0,就说这条路是一个负权回路。
如果存在负权回路,只输出一行 −1;如果不存在负权回路,再求出一个点S到每个点的最短路的长度。约定:S 到 S 的距离为
0,如果 S 与这个点不连通,则输出 NoPath。
输入
第一行三个正整数,分别为点数 N,边数 M,源点 S;
以下 M 行,每行三个整数 a,b,c,表示点 a,b之间连有一条边,权值为 c。
输出
如果存在负权环,只输出一行 −1,否则按以下格式输出:共 N 行,第 i 行描述 S 点到点 i 的最短路
如果 S 与 i 不连通,输出 NoPath;
如果 i=S,输出 0。
其他情况输出 S 到 i 的最短路的长度。
输入示例
6 8 1
1 3 4
1 2 6
3 4 -7
6 4 2
2 4 5
3 6 3
4 5 1
3 5 4
输出示例
0
6
4
-3
-2

先用DFS判断负环,然后跑最短路即可。

DFS具体判断负环的方法是:记录一个vis数组,表示在你这次搜索过程中有没有走到这个点,如果在搜索的时候,发现这个目标点vis==1了,并且你还可以更新这个目标点的dis,那么就存在负环。因为这就相当于你跑完一圈,dis又少了,那么这个环肯定是负的。

这里有一个优化:是大佬YSF、SYF和我们清华毕业的数学老师姚璐提出并证明的。一般判断负环时,我们会把dis初始值赋成INF,但是实际上,我们可以赋0。相当于DFS跑最短路的时候,遇到正边就不跑了,这样会节省很大的时间复杂度。那么怎么证明正确性呢?

首先,我们需要证明一点,对于一个负环,一定有一个点,从这个点到第起始点的所有边权都为负,因为如果有正的,dis为0的情况可能会被正的卡住。那么又怎么证明这个呢?

我们可以画一个函数图像,x坐标表示负环上的每个点,y表示到x点时经过的边权。画出来后,你会发现,一定有一个峰值,然后对于这个峰值建系,它右侧的值全都是负的了。

具体代码如下(注意我的dis赋成0也可以AC,也是一个上面说法的验证):

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <queue>
#define REP(i,k,n) for(int i=k;i<=n;i++)
#define in(a) a=read()
using namespace std;
inline int read(){
int x=,f=;
char ch=getchar();
for(;!isdigit(ch);ch=getchar())
if(ch=='-')
f=-;
for(;isdigit(ch);ch=getchar())
x=x*+ch-'';
return x*f;
}
int T;
int flag=;
int n,m,s;
int total=,nxt[],head[],to[],val[];
int vis[],dis[],book[];
int q[];
inline void adl(int a,int b,int c){
total++;
to[total]=b;
val[total]=c;
nxt[total]=head[a];
head[a]=total;
return ;
}
queue <int> Q;
inline void dfs(int u){
book[u]=;
for(int e=head[u];e;e=nxt[e]){
if(dis[to[e]]>dis[u]+val[e]){
dis[to[e]]=dis[u]+val[e];
if(vis[to[e]]){
flag=;
return ;
}
if(flag)
return ;
vis[to[e]]=;
dfs(to[e]);
vis[to[e]]=;
}
}
return ;
}
void SPFA(int st){
memset(vis,,sizeof(vis));
memset(dis,,sizeof(dis));
int hea=,tail=;
//q[hea]=st;
Q.push(st);
dis[st]=;
while(!Q.empty()/*tail>=hea*/){
int u=Q.front();
//hea++;
Q.pop();
vis[u]=;
for(int e=head[u];e;e=nxt[e])
if(dis[to[e]]>dis[u]+val[e]){
dis[to[e]]=dis[u]+val[e];
if(!vis[to[e]]){
vis[to[e]]=;
Q.push(to[e]);
}
}
}
return ;
}
int main()
{
total=flag=;
//memset(dis,127,sizeof(dis));
in(n);in(m);in(s);
int a,b,c;
REP(i,,m){
in(a);in(b);in(c);
adl(a,b,c);
}
REP(i,,n)
if(!book[i]){
memset(vis,,sizeof(vis));
dfs(i);
if(flag) break;
}
if(flag){
cout<<-<<endl;
return ;
}
SPFA(s);
REP(i,,n)
if(dis[i]>)
cout<<"NoPath"<<endl;
else cout<<dis[i]<<endl;
}

Loj10086 Easy SSSP的更多相关文章

  1. vijosP1053 Easy sssp

    vijosP1053 Easy sssp 链接:https://vijos.org/p/1053 [思路] SPFA. 题目中的陷阱比较多,但是只要中规中矩的写SPFA诸如:s与负圈不相连,有重边的情 ...

  2. Easy sssp

    Easy sssp 时间限制: 1 Sec  内存限制: 128 MB提交: 103  解决: 20[提交][状态][讨论版] 题目描述 输入数据给出一个有N(2  < =  N  < = ...

  3. Easy sssp(spfa)(负环)

    vijos    1053    Easy sssp 方法:用spfa判断是否存在负环 描述 输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,00 ...

  4. SPFA_YZOI 1662: Easy sssp

    题目描述 输入数据给出一个有N(2  < =  N  < =  1,000)个节点,M(M  < =  100,000)条边的带权有向图.  要求你写一个程序,  判断这个有向图中是 ...

  5. Vijos1053 Easy sssp[spfa 负环]

    描述 输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,000)条边的带权有向图. 要求你写一个程序, 判断这个有向图中是否存在负权回路. 如果从一 ...

  6. vijos 1053 Easy sssp

    描述 输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,000)条边的带权有向图. 要求你写一个程序, 判断这个有向图中是否存在负权回路. 如果从一 ...

  7. Easy sssp(vijos 1053)

    描述 输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,000)条边的带权有向图. 要求你写一个程序, 判断这个有向图中是否存在负权回路. 如果从一 ...

  8. Vijos——T1053 Easy sssp

    https://vijos.org/p/1053 描述 输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,000)条边的带权有向图. 要求你写一个程 ...

  9. Easy sssp(spfa判负环与求最短路)

    #include<bits/stdc++.h> using namespace std; int n,m,s; struct node{ int to,next,w; }e[]; bool ...

随机推荐

  1. linux学习记录.1.安装

    最近想了想决定开始学习linux. 在百度了一番后开始了安装,虚拟机VirtualBox,ubuntu. 基于VirtualBox虚拟机安装Ubuntu图文教程: http://blog.csdn.n ...

  2. android Timer TimerTask用法笔记

    Android中经常会遇到执行一些周期性定时执行的任务.初学的时候经常会使用Thread.sleep()方法.在android中,有Timer可以专门干这个事情. 先看看Timer.class中都是些 ...

  3. Tomcat参数调优包括日志、线程数、内存【转】

    [Tomcat中日志打印对性能测试的影响] 一般都提供了这样5个日志级别: ▪ Debug ▪ Info ▪ Warn ▪ Error ▪ Fatal 由于性能测试需要并发进行压力测试,如果日志级别是 ...

  4. Bootstrap的使用。。。

    概览 深入了解 Bootstrap 底层结构的关键部分,包括我们让 web 开发变得更好.更快.更强壮的最佳实践. HTML5 文档类型 Bootstrap 使用到的某些 HTML 元素和 CSS 属 ...

  5. HTML+CSS小技巧

    网页标题前引入ico图标 <link rel="shortcut icon" href="img/icoTest.ico">

  6. ~Delphi const 杂谈~

    来自:http://www.cnblogs.com/tibetwolf/articles/1785744.html ------------------------------------------ ...

  7. POJ 2186 Popular cows(Kosaraju+强联通分量模板)

    题目链接:http://poj.org/problem?id=2186 题目大意:给定N头牛和M个有序对(A,B),(A,B)表示A牛认为B牛是红人,该关系具有传递性,如果牛A认为牛B是红人,牛B认为 ...

  8. Python+Selenium 自动化实现实例-单元测试报告

    代码如下: # -*- coding: utf-8 -*- from selenium import webdriver import unittest,time import HTMLTestRun ...

  9. 【转+整理+答案】python315+道面试题

    提示 自己整理的答案,很局限,如有需要改进的地方,或者有更好的答案,欢迎提出! [合理利用 Ctrl+F 提高查找效率] 第一部分 Python基础篇(80题) 1.为什么学习Python? # 因为 ...

  10. 远程连接 mysql 数据库连接不上的解决方案

    今天用Navicat访问虚拟机上的mysql,无法访问报cannot connect(10038). 首先看是否可以telnet,本机cmd,telnet 10.10.10.10 3306,结果是连接 ...