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 ...
随机推荐
- Color.js 方便修改颜色值
这并不是npm上比较活跃的clolr包的中文文档,不过它在最后提到了: The API was inspired by color-js. Manipulation functions by CSS ...
- IIS 配置错误:不能在此路径中使用此配置节。如果在父级别上锁定了该节,便会出现这种情况。 HTTP 错误 500.19
因为 IIS 7 采用了更安全的 web.config 管理机制,默认情况下会锁住配置项不允许更改.运行命令行 %windir%\system32\inetsrv\appcmd unlock conf ...
- centOS中如何修改运行级别!
在图形化界面可以用Ctrl+Alt+F2进入命令行窗口 * 假如你使用了虚拟机,有可能会出现不能进去的问题,原因是因为热键冲突 * 解决办法:修改热键就行了 edit→parameter→hot ke ...
- 关于海康视频采集卡的简介---基于pci的插潮采集卡
vga 640x480 qvga vga的1/4,宽高分别是vga的一半 (1)采集类型 海康威视 DS-2CE16A2P-IT3P 700TVL 1/3" DIS ICR 红外防水筒型摄像 ...
- python 基础 8.1 r 正则对象
...
- 九度OJ 1018:统计同成绩学生人数 (基础题)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:8807 解决:4651 题目描述: 读入N名学生的成绩,将获得某一给定分数的学生人数输出. 输入: 测试输入包含若干测试用例,每个测试用例的 ...
- 3D立方体旋转动画
在线演示 本地下载
- g2o的一般过程
1.自己定义顶点类.边类或者用已经有的.1.1定义顶点例子class CurveFittingVertex: public g2o::BaseVertex<3, Eigen::Vector3d& ...
- 【LeetCode】两个有序数组合成一个有序数组
a = [1,3,5,7,9]b = [2,4,6,8,10]c= [] while len(a) > 0: if len(b) == 0: c.extend(a) break min_num ...
- css(5)
我觉得css中的margin:10px 0 0 4px; 先是margin-top生效,而margin-bottom则不生效.