题目连接: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; }
时间: 2024-10-24 20:02:03