题目连接:http://acm.nyist.net/JudgeOnline/problem.php?pid=973
算法分析:
spfa+负环判定
在传功的过程中如果因为f<1导致逐渐变小,那么即可以负环判定
#include <iostream>
#include<cstdio>
#include <cstdlib>
#include <queue>
#include <vector>
using namespace std;
const int MAXN=505;
const int INF=0x7FFFFFFF;
struct edge
{
int to;
double weight;
};
vector<edge> adjmap[MAXN];//邻接表
bool in_queue[MAXN];//顶点是否在队列中
int in_sum[MAXN];//顶点入队次数
double dist[MAXN];//源点到各点的最短路径
int nodesum;//顶点数
int edgesum;//边数
bool SPFA(int source)
{
queue<int> dq;
int i,j,x,to;
for(i=1;i<=nodesum;i++)
{
in_sum[i]=0;
in_queue[i]=false;
dist[i]=0;
}
dq.push(source);
in_sum[source]++;
dist[source]=1.0;
in_queue[source]=true;
while(!dq.empty())
{
x=dq.front();
dq.pop();
in_queue[x]=false;
for(i=0;i<adjmap[x].size();i++)
{
double f=adjmap[x][i].weight;
to=adjmap[x][i].to;
if(dist[to]-dist[x]*f<0.01)
{
dist[to]=dist[x]*f;
if(!in_queue[to])
{
dq.push(to);
in_queue[to]=true;
if(++in_sum[to]>=nodesum) return true;
}
}
}
}
return false;
}
int main()
{
int n,i,s,e;
double w;
scanf("%d",&n);
while(n--){
edge temp;
scanf("%d%d",&nodesum,&edgesum);
for(i=1;i<=nodesum;i++)
adjmap[i].clear();//清空邻接表
for(i=1;i<=edgesum;i++)
{
scanf("%d%lf%d",&s,&w,&e);
temp.to=e;
temp.weight=w;
adjmap[s].push_back(temp);
}
if(SPFA(1))
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
return 0;
}原文:http://blog.csdn.net/u014492609/article/details/45173765