poj1860(spfa)

来源:互联网 发布:淘宝大学vip靠谱吗 编辑:程序博客网 时间:2024/05/20 03:42

两种情况YES,一种是存在正权回路;
       一种是求最长路后,实现了增值,也是YES;
用spfa来判断是否存在正权回路,其实spfa是可以用来判断是否存在回路的,不管是正权还是负权,只不过它们松弛的条件不同,正权的话,我们是往dis[]权值增大的方向松弛,负权的话,我们是往dis[]权值减少的方向松弛,然后判断是否存在回路只要看有没有一点入队列的次数大于n就行了用spfa来判断是否存在正权回路,其实spfa是可以用来判断是否存在回路的,不管是正权还是负权,只不过它们松弛的条件不同,正权的话,我们是往dis[]权值增大的
 
如果存在一个环(从某个点出发又回到自己的路径),而且这个环上所有权值之和是负数,那这就是一个负权环,也叫负权回路;同理正权回路;
#include <iostream>#include <cstdio>#include <cstring>#include <stdlib.h>#include <math.h>#include <queue>#include <algorithm>using namespace std;#define N 210#define INF 0xfffffffdouble dist[N], V;int cnt, Head[N], num[N], vis[N];int n, m, s;struct Edge{    int v, next;    double r, c;}e[N];void Add(int u, int v, double r, double c){    e[cnt].v = v;    e[cnt].r = r;    e[cnt].c = c;    e[cnt].next = Head[u];    Head[u] = cnt++;}//spfa模板/*int spfa(int src,int n){//用队列实现int i;memset(cnt,0,sizeof(cnt));//入队次数memset(vis,false,sizeof(vis));//for(i=1;i<=n;i++)dist[i]=INF;dist[src]=0;queue<int>Q;Q.push(src);vis[src]=true;++cnt[src];while(!Q.empty()){    int u,v;    u=Q.front();Q.pop();vis[u]=false;    for(i=head[u];i!=-1;i=nxt[i]){        v=pnt[i];        if(1==relax(u,v,cost[i])&&!vis[v]){            Q.push(v);vis[v]=true;            if((++cnt[v])>n)return -1;//cnt[i]为入队列次数,用来判断是否存在负权回路        }    }}if(dist[n]==INF)return -2;//src和n不可达,有些题目可省return dist[n];//返回src到n的最短距离,根据题意不同而改变}*/bool spfa()///spfa模板;{    memset(vis, 0, sizeof(vis));    memset(num, 0, sizeof(num));    queue<int>Q;    vis[s] = 1;    dist[s] = V;    Q.push(s);    num[s]++;    while(Q.size())    {        int p=Q.front();        Q.pop();        vis[p] = 0;        for(int i=Head[p]; i!=-1; i=e[i].next)        {            int q = e[i].v;            if(dist[q] < (dist[p] - e[i].c) * e[i].r)///注意松弛的变化;            {                dist[q] = (dist[p] - e[i].c) * e[i].r;                if(!vis[q])                {                    vis[q] = 1;                    Q.push(q);                    num[q] ++;                    if(num[q]>n)                        return true;///存在正权回路;                }            }        }    }    if(dist[s]>V)///最长路后,实现了增值;        return true;    return false;}int main(){    int a, b;    double rab, rba, cab, cba;    while(scanf("%d%d%d%lf", &n, &m, &s, &V)!=EOF)    {        cnt = 0;        memset(Head, -1, sizeof(Head));        memset(dist, 0, sizeof(dist));        for(int i=1; i<=m; i++)        {            scanf("%d%d%lf%lf%lf%lf", &a, &b, &rab, &cab, &rba, &cba);            Add(a, b, rab, cab);            Add(b, a, rba, cba);        }        if( spfa() )            printf("YES\n");        else            printf("NO\n");    }    return 0;}








0 0
原创粉丝点击