VIJOS 1552 Easy sssp
2013-10-09 21:25
190 查看
描述
输入数据给出一个有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的最短路的长度.
样例1
样例输入
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时记录每一个点是否搜索过
枚举每一个没搜过的点尝试作为起点spfa
最后输出
要开到long long
可以加上一句判断d太小就默认存在负环的语句
这样就可以过了
#include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std; const int inf=999999999; const int len=1111; const int lim=100010; int m,n,start; struct self{int x,y,w;}s[lim]; int first[lim],next[lim]; queue<int>q; bool inq[len]; bool flag[len]; int t[len]; long long d[len]; //需要开成long long 如果下面写那一句可以用int int a,b,c; bool ishave(int i) { int a; while(!q.empty())q.pop(); memset(inq,0,sizeof(inq)); memset(t,0,sizeof(t)); q.push(i); for(a=1;a<=m;a++)d[a]=inf; d[i]=0; while(!q.empty()) { int u=q.front(); q.pop(); inq[u]=0; flag[u]=1; for(int e=first[u];e!=-1;e=next[e]) if(d[s[e].y]>d[u]+s[e].w) { d[s[e].y]=d[u]+s[e].w; if(!inq[s[e].y]) { inq[s[e].y]=1; q.push(s[e].y); t[s[e].y]++; //if(t[s[e].y]>m||d[s[e].y]<-inf)//写这一句可以过 但是不能保证结果正确性 if(t[s[e].y]>m) return true; } } } return false; } void print() { int a; for(a=1;a<=m;a++) if(d[a]==inf)cout<<"NoPath"<<'\n'; else cout<<d[a]<<'\n'; } int main() { memset(first,-1,sizeof(first)); memset(next,-1,sizeof(next)); scanf("%d%d%d",&m,&n,&start); for(a=1;a<=n;a++) { scanf("%d%d%d",&s[a].x,&s[a].y,&s[a].w); next[a]=first[s[a].x]; first[s[a].x]=a; } for(a=1;a<=m;a++) if(!flag[a]) { flag[a]=1; if(ishave(a)) { cout<<-1<<'\n'; return 0; } } ishave(start); print(); return 0; }
相关文章推荐
- Vijos1450 包裹快递[二分答案]
- 【vijos1677】【KMP】陶陶的名字
- [NOIP2014][vijos1914]子矩阵(dp)
- Vijos 1164曹冲养猪(中国剩余定理)
- Vijos P1901 学姐的钱包
- Vijos P1196吃糖果游戏[组合游戏]
- vijos 1580最大矩形(单调栈)
- 【Vijos1250】最勇敢的机器人(并查集,分组背包DP)
- [vijos1007] 绕钉子的长绳子
- vijos P1412多人背包 DP的前k优解
- vijos 1540 月亮之眼 并查集
- Vijos 1565 多边形 【区间DP】
- vijos1048——送给圣诞夜的贺卡
- Vijos 1193 扫雷 【动态规划】
- 集训-vijos选课(树形DP)
- Vijos 1036题:安装服务器
- Vijos 1433题:火炬手之梦
- Vijos 1335题:数独验证
- Vijos P1449 字符串还原【密码】
- vijos1904 学姐的幸运数字