CSU1978-LXX的图论题-SPFA判环
Description
由于lxx的图论和数据结构太弱了,大佬Z决定为lxx补一补。于是大佬Z为lxx出了一道题目,题目如下:给出一张有向图,图中有n个点,m条边,每条边上都有一个权值w,问图中是否存在满足以下条件的点i,j,…p使得不等式w[i][j] * w[j][k] * …. * w[p][i]<1成立。奈何lxx太弱了,他决定寻求你的帮助。
Input
多组输入,以文件结尾。第一行两个整数n( 1<=n<=500 ),m( 1<=m<=n*(n-1)/2 ),接下来m行,每行3个数x,y,z,(x≠y):表示x到y有一条边,权值为z(0
Output
如果存在满足题目所描述的式子,输出“YES”,否则输出“NO”。
Sample Input
2 2
1 2 0.9
2 1 1.2
6 4
1 2 0.1
2 4 0.8
4 1 12
4 1 15
Sample Output
NO
YES
Hint
点的编号为1~n
思路
就是SPFA判环嘛
首先把式子取个对数从乘法变成加法,于是就是裸的判负环了
但是我比赛的时候没A,不知道乘法会精度丢失,毕竟500个……
AC代码
/**************************************
*Source : CSU1978
*Knowledge Point : SPFA_PENDING_CYCLE
*Author : CSUzick
**************************************/
#include <cstdio>
#include <iomanip>
#include <cstring>
#include <iostream>
#include <stack>
#include <vector>
#include <queue>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <set>
#include <bitset>
#include <map>
#define LL long long
#define mk(a,b) make_pair(a,b)
#define ULL unsigned long long
#define mem(a,n) memset(a,n,sizeof(a))
#define fread freopen("in.txt","r",stdin)
#define fwrite freopen("out.txt","w",stdout)
#define N 550
#define INF 0x3f3f3f3f
#define eps 1e-12
using namespace std;
struct Edge{
int from,to;
double dist;
Edge(int u,int v,double d):from(u),to(v),dist(d){};
};
struct SPFA{
vector<Edge> edges;
vector<int> G[N];
bool inque[N];
double d[N];
int cnt[N];
int n,m;
void init(int n){
this->n=n;
for(int i=0;i<=n;++i){
G[i].clear();
}
edges.clear();
}
void AddEdge(int from,int to,double dist){
edges.push_back(Edge(from,to,dist));
m=edges.size();
G[from].push_back(m-1);
}
bool spfa(){
queue<int> que;
memset(inque,0,sizeof(inque));
memset(cnt,0,sizeof(cnt));
for(int i=0;i<=n;++i){
que.push(i);
d[i]=0;
inque[i]=false;
}
while(!que.empty()){
int temp=que.front();
if(cnt[temp]==n){
return true;
}
que.pop();
inque[temp]=false;
for(int i=0;i<G[temp].size();++i){
Edge &e=edges[G[temp][i]];
if(d[e.to]-d[temp]-e.dist>eps){
d[e.to]=d[temp]+e.dist;
if(!inque[e.to]){
que.push(e.to);
inque[e.to]=true;
if(++cnt[e.to]>=n) return true;
}
}
}
}
return false;
}
};
SPFA SMF;
int main()
{
int n,m,u,v;
double c;
while(~scanf("%d%d",&n,&m)){
SMF.init(n);
while(m--){
scanf("%d%d%lf",&u,&v,&c);
SMF.AddEdge(u,v,log2(c));
}
if(SMF.spfa()){
printf("YES\n");
}else{
printf("NO\n");
}
}
return 0;
}