vijos:P1053Easy sssp(spfa判环)
描述
输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,000)条边的带权有向图.
要求你写一个程序, 判断这个有向图中是否存在负权回路. 如果从一个点沿着某条路径出发, 又回到了自己, 而且所经过的边上的权和小于0, 就说这条路是一个负权回路.
如果存在负权回路, 只输出一行-1;
如果不存在负权回路, 再求出一个点S(1 <= S <= N)到每个点的最短路的长度. 约定: S到S的距离为0, 如果S与这个点不连通, 则输出NoPath.
格式
输入格式
第一行: 点数N(2 <= N <= 1,000), 边数M(M <= 100,000), 源点S(1 <= S <= N);
以下M行, 每行三个整数a, b, c表示点a, b(1 <= a, b <= N)之间连有一条边, 权值为c(-1,000,000 <= c <= 1,000,000)
输出格式
如果存在负权环, 只输出一行-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
7
思路:spfa算法,不过这道题存在陷阱。第一存在重边,解决方法用邻接矩阵表示图,保留权值最小的一个。第二图可能不连通,解决方法对每个结点进行spfa,为了优化时间,设置一个used数组标志已经遍历过的结点,遍历过的结点无需再进行spfa。最后加上若d[s]<0则存在负环。
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN=;
const int INF=0x7f7f7f7f;
int n,m,s;
int contain;
int mp[MAXN][MAXN];
int d[MAXN];
int cnt[MAXN];
bool vis[MAXN],used[MAXN];
void addedge(int u,int v,int w)
{
if(mp[u][v]>w)
mp[u][v]=w;
} bool spfa(int scource)
{
for(int i=;i<=n;i++)
{
d[i]=INF;
vis[i]=false;
} queue<int> que;
que.push(scource);
vis[scource]=true;
used[scource]=true;
d[scource]=;
while(!que.empty())
{
int now = que.front();que.pop();
vis[now]=false;
for(int i=;i<=n;i++)
{
if(now==i||mp[now][i]==INF) continue;
if(d[i]>d[now]+mp[now][i])
{
d[i]=d[now]+mp[now][i];
if(d[scource]<) return true;
if(!vis[i])
{
used[i]=vis[i]=true;
que.push(i);
cnt[i]++;
if(cnt[i]>=n) return true;
}
} }
}
return false;
} void solve()
{
for(int i=;i<=n;i++)
{
if(!used[i]&&spfa(i))
{
printf("-1\n");
return ;
}
}
if(spfa(s))
{
printf("-1\n");
}
else
{
for(int i=;i<=n;i++)
if(d[i]==INF) printf("NoPath\n");
else printf("%d\n",d[i]);
}
} int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=;i<=n;i++)
for(int j=;j<=n;j++)
if(i==j) mp[i][j]=;
else mp[i][j]=mp[j][i]=INF;
for(int i=;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
}
solve(); return ;
}
spfa+前向星可解决重边问题。d[source][source]<0则存在负环
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int MAXN=;
const int INF=0x3f3f3f3f;
struct Edge{
int to,w,next;
}es[];
int head[MAXN],tot;
int n,m,source;
int d[MAXN][MAXN],vis[MAXN],used[MAXN];
void addedge(int u,int v,int w)
{
es[tot].to=v;
es[tot].w=w;
es[tot].next=head[u];
head[u]=tot++;
}
bool spfa(int s)
{
for(int i=;i<=n;i++)
{
d[s][i]=INF;
vis[i]=;
}
queue<int> que;
que.push(s);
d[s][s]=;
vis[s]=;
used[s]=;
while(!que.empty())
{
int u=que.front();que.pop();
vis[u]=;
for(int i=head[u];i!=-;i=es[i].next)
{
Edge e=es[i];
if(d[s][e.to]>d[s][u]+e.w)
{
d[s][e.to]=d[s][u]+e.w;
if(d[s][s]<) return true;
if(!vis[e.to])
{
que.push(e.to);
vis[e.to]=;
used[e.to]=;
}
}
}
}
return false;
}
void solve()
{
if(spfa(source))
{
printf("-1\n");
return ;
}
for(int i=;i<=n;i++)
{
if(!used[i]&&spfa(i))
{
printf("-1\n");
return ;
}
}
for(int i=;i<=n;i++)
{
if(d[source][i]==INF) printf("NoPath\n");
else printf("%d\n",d[source][i]);
}
}
int main()
{
memset(head,-,sizeof(head));
scanf("%d%d%d",&n,&m,&source);
for(int i=;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w);
}
solve(); return ;
}
vijos:P1053Easy sssp(spfa判环)的更多相关文章
- 2018.09.09 poj2949Word Rings(01分数规划+spfa判环)
传送门 这题要先巧妙的转化一下. 对于每个字符串,我们把头尾的两个小字符串对应的点连边,边权是这个字符串的长度. 这样最多会出现26*26个点. 这个时候就只用求出边权和跟边数的最大比值了. 这个显然 ...
- POJ 1860 Currency Exchange【SPFA判环】
Several currency exchange points are working in our city. Let us suppose that each point specializes ...
- 【BZOJ 3232】圈地游戏 二分+SPFA判环/最小割经典模型
最小割经典模型指的是“一堆元素进行选取,对于某个元素的取舍有代价或价值,对于某些对元素,选取后会有额外代价或价值”的经典最小割模型,建立倒三角进行最小割.这个二分是显然的,一开始我也是想到了最小割的那 ...
- POJ 2240 Arbitrage (spfa判环)
Arbitrage Arbitrage is the use of discrepancies in currency exchange rates to transform one unit of ...
- 2018.09.12 poj3621Sightseeing Cows(01分数规划+spfa判环)
传送门 01分数规划板题啊. 发现就是一个最优比率环. 这个直接二分+spfa判负环就行了. 代码: #include<iostream> #include<cstdio> # ...
- Vijos1053 Easy sssp[spfa 负环]
描述 输入数据给出一个有N(2 <= N <= 1,000)个节点,M(M <= 100,000)条边的带权有向图. 要求你写一个程序, 判断这个有向图中是否存在负权回路. 如果从一 ...
- POJ 3259 Wormholes(SPFA判负环)
题目链接:http://poj.org/problem?id=3259 题目大意是给你n个点,m条双向边,w条负权单向边.问你是否有负环(虫洞). 这个就是spfa判负环的模版题,中间的cnt数组就是 ...
- Poj 3259 Wormholes(spfa判负环)
Wormholes Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 42366 Accepted: 15560 传送门 Descr ...
- poj1860(spfa判正环)
题目连接:http://poj.org/problem?id=1860 题意:有多种从a到b的汇率,在你汇钱的过程中还需要支付手续费,那么你所得的钱是 money=(nowmoney-手续费)*rat ...
随机推荐
- 摩托罗拉SE955 One Discrete Length,Two Discrete Lengths,Length Within Range 相关解释
motorola scanner datasheet相关解释(下面通过Simple Serial Interface(SSI)进行设置,非扫描官方datasheet的设置条码): One Discre ...
- HDFS源码分析数据块汇报之损坏数据块检测checkReplicaCorrupt()
无论是第一次,还是之后的每次数据块汇报,名字名字节点都会对汇报上来的数据块进行检测,看看其是否为损坏的数据块.那么,损坏数据块是如何被检测的呢?本文,我们将研究下损坏数据块检测的checkReplic ...
- ZIP解压缩文件的工具类【支持多级文件夹|全】
ZIP解压缩文件的工具类[支持多级文件夹|全] 作者:Vashon 网上有非常多的加压缩演示样例代码.可是都仅仅是支持一级文件夹的操作.假设存在多级文件夹的话就不行了. 本解压缩工具类经过多次检查及重 ...
- 【Unity 3D】学习笔记三十:游戏元素——游戏地形
游戏地形 在游戏的世界中,必然会有非常多丰富多彩的游戏元素融合当中. 它们种类繁多.作用也不大同样.一般对于游戏元素可分为两种:经经常使用.不经经常使用.经常使用的元素是游戏中比較重要的元素.一般须要 ...
- EntityFramework走马观花之CRUD(中)
如果是独立的实体对象,在底层数据库中它对应一张独立的表,那么,对它进行新建.删除和修改没有任何难度,实在不值浪费笔墨在它上头. 在现实项目中,完全独立的对象少之又少,绝大多数情况都是对象之间有着紧密的 ...
- 出版物排版软件——对XML数据进行排版、浏览、转换、打印
XML和XSL进行排版的功能强大的软件,并将排版结果进行打印或转换成各种各样的文件格式,满足各方需求. 随着出版物电子排版方式的普及,大部头出版物的排版,越来越多的应用在人们的工作中.比如,惠普公 ...
- python mmap使用记录
1.写文件 with open('??', 'r+b') as f: with contextlib.closing(mmap.mmap(f.fileno(), size, flags=mmap.MA ...
- 【AWS】亚马逊云常用服务解释
新公司使用的是亚马逊服务,刚开始的时候,对很多名词不太明白,总结了一下如下 1,EC2 这个是亚马逊的一种服务器服务,可以理解为跟vmware差不多,EC2为虚拟机提供载体,EC2上跑虚拟机服务器. ...
- render 的执行流程
流程 : render 只能识别 字符串,对于其他的css,html,js,jquery样式是不能识别的,它会将文件中的内容解析称为字符串拿到前端页面,浏览器进行渲染. 例如 : # 视图函数 de ...
- jQuery的事件绑定和解除
1 . 绑定事件 语法 : bind(type,data,fn) 描述 : 为每一个匹配的特定元素(像 click)绑定一个事件处理器函数. type(String) : 事件类型 data(Obje ...