JSK习题:闯关游戏-SPFA,判断环

这里写图片描述

题意:

。。。

思路:

先将所有输入w取反,表示消耗,SPFA中记录每个点入队次数,若v入队次数>n,表示存在负环,则记d[v]=-inf,且不再入队

代码:

#include <iostream>
#include <string.h>
#include <queue>
using namespace std;
const int MAX_N=1000000;
int n;
struct edge
{
    int u,to,next,cost;
}e[MAX_N];
int p[MAX_N],eid=0;
void init()
{
    memset(p,-1,sizeof(p));
    eid=0;
}
void insert(int u,int v,int w)
{
    e[eid].to=v;
    e[eid].cost=w;
    e[eid].next=p[u];
    p[u]=eid++;
}
bool inq[MAX_N];
int cnt[MAX_N];
int d[MAX_N];  // 如果到顶点 i 的距离是 0x3f3f3f3f,则说明不存在源点到 i 的最短路
void spfa(int s)
{
    memset(inq, 0, sizeof(inq));
    memset(d, 0x3f, sizeof(d));
    memset(cnt,0,sizeof(cnt));
    int heal=100;
    d[s] = 0;
    inq[s] = true;
    cnt[s]=1;
    queue<int> q;
    q.push(s);
    while (!q.empty())
    {
        for(int i=1;i<=n;i++)                        //入队次数超过n,表示存在负环,将其d改为-inf,不再入队
        {
            if(cnt[i]>n)
                d[i]=-1000000;
        }
        int u = q.front();
        q.pop();
        inq[u] = false;
        for (int i = p[u]; i != -1; i = e[i].next) {
            int v = e[i].to;
            if (d[u] + e[i].cost < d[v]) {
                d[v] = d[u] + e[i].cost;
                if (!inq[v] && cnt[v]<n)                 //入队次数超过n表示有环,不再入队
                {
                    q.push(v);
                    cnt[v]++;
                    inq[v] = true;
                }
            }
        }
    }
}
int main()
{
    std::ios::sync_with_stdio(false);
    init();
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        int w,m,v;
        cin>>w>>m;
        for(int j=0;j<m;j++)
        {
            cin>>v;
            insert(i,v,-w);         //w取反表示消耗
        }
    }
    spfa(1);
    if(100-d[n]>0)
        cout<<"Yes"<<endl;
    else
        cout<<"No"<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_43093481/article/details/82319077