LA 3310 SPFA判正环

本文深入探讨了SPFA算法的原理与优化方法,并通过具体案例解析如何利用该算法进行正环判断。此外,还提供了SPFA算法在实际问题中的应用实例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

复习判正环两种方法:

1、spfa入队总次数达2*(N+M)则认为存在正环

2、所有点d数组初值为0+spfa_dfs

参考 《spfa的优化及应用》——姜碧野

之前做过的另一题http://blog.youkuaiyun.com/chm517/article/details/9389837

#include<stack>
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<vector>
#include<set>
#include<algorithm>
#include<queue>
#define sqr(x) (x)*(x)
#define f1 first
#define f2 second
#define pb push_back
#define fr(i,x,y) for(int i=x;i<=y;++i)
#define ms(x,y) memset(x,y,sizeof(x))
#define sqr(x) (x)*(x)
typedef long long ll;
const ll inf=(1ll)<<50;
#define N 100005
#define M 1000005
const int maxans=1000000000;
using namespace std;
struct edge{
    int to,next;
    ll w;
}e[M];
struct rr{
    int op;
    int id;
    bool operator<(const rr&oth)const{
        return id<oth.id;
    }
}b[N];
struct line{
    int op;
    ll tim;
    int num;
}a[N];
deque<int> q;
int head[N],vis[N],typ[N],cen[N],id[N],num[N],fun[N];
ll d[N];
int n,o,m,nown,ce,sz,all,idd;
ll ans3310;
void add(int x,int y,ll z)
{
    if (y>nown) return;
    all+=z;
    e[o].to=y;
    e[o].next=head[x];
    e[o].w=z;
    head[x]=o++;
}

inline bool maximize(ll& a,ll b)
{
    if (b<=a) return 0;
    a=b;
    return 1;
}
bool spfa(int now)
{    vis[now]=1;
     for (int k=head[now];k!=-1;k=e[k].next)
             if (d[e[k].to]<d[now]+e[k].w)
             {  d[e[k].to]=d[now]+e[k].w;
                if (!vis[e[k].to])
                    if  (spfa(e[k].to)) return 1;else;
                else return 1;
             }
    vis[now]=0;
    return 0;
}
bool spfa_getans(int n,int initial)
{
    fr(i,1,n){d[i]=0;vis[i]=0;}
    if (spfa(1)) return 0;//RIGHT!
    //WA!in this case{die,……} fr(i,1,n)if (spfa(i)) return 0;
    fr(i,1,n){d[i]=0;vis[i]=0;num[i]=0;}
    d[1]=initial;
    while (!q.empty()) q.pop_front();
    q.push_front(1);vis[1]=1; num[1]++;

    int j,v,RD=0,RDM=(o+n)*2+10;
    while (!q.empty())
    {
        j=q.front();q.pop_front();
        vis[j]=0;
        if (typ[j]){ans3310=max(ans3310,d[j]);continue;}
        for (int k=head[j];k!=-1;k=e[k].next)
            {   v=e[k].to;
                if (maximize(d[v],d[j]+e[k].w))
                    {   if (d[v]>all) return 0;
                        if (!vis[v]) {num[v]++;
                                      if (!q.empty())
                                      if(d[v]<q.front())q.push_front(v);else q.push_back(v);
                                      else q.push_back(v);
                                      RD++;
                                      //if (RD>RDM) return 0;
                                      if  (num[v]>n) return 0;
                                     }
                    }
            }

    }
    return 1;
}


char s[100];
stack<ll> st2;
int aa[N],bb[N],cc[N];
void ret()
{   fun[n+1]=1;//fun[n+1]=int(log(n+1)/log(10)+1e-9)+1;
    puts("infinity");
}
void ggg(int l,int r)
{ 
   fr(j,l,r-1)
            {
                if (a[j].op==1) add(id[j],id[a[j].num],fun[a[j].num]),add(id[j],id[j+1],fun[j+1]);
                if (a[j].op==2) add(id[j],id[a[j].num],fun[a[j].num]);
                if (a[j].op==3) add(id[j],id[j+1],fun[j+1]);
                if (a[j].op==5) typ[id[j]]=1;
            }
   int j=r;if (a[j].op==5) typ[id[j]]=1;
}

bool doit()
{   n=0; m=0; ans3310=0;
    int re=0,len,yes,dieflag=0;
    char *ss,*s2;
    while (gets(s))
        {
            len=strlen(s);
            yes=0;
            fr(j,0,len-1)
                {if (s[j]=='i'||s[j]=='I'){a[++n].op=1;yes=1;ss=s+j+4;break;}
                 if (s[j]=='j'||s[j]=='J'){a[++n].op=2;yes=1;ss=s+j+4;break;}
                 if (s[j]=='p'||s[j]=='P'){a[++n].op=3;yes=1;ss=s+j+4;break;}
                 if (s[j]=='l'||s[j]=='L'){a[++n].op=4;yes=1;ss=s+j+4;break;}
                 if (s[j]=='d'||s[j]=='D'){dieflag=1;a[++n].op=5;yes=1;ss=s+j+3;break;}
                }
            if (!yes){re=1; break;}
            while (*ss==' ') ss++;
            s2=ss;
            int tmp=0;ll x=0;
            while (*s2>='0'&&*s2<='9'){tmp++;if (tmp<10)x=x*10+(*s2)-'0';s2++;}
            if (a[n].op==1||a[n].op==2||a[n].op==4)
                {   if (tmp<6||(tmp==6&&x==1000000))
                    a[n].num=int(x);else puts("~~~~~~~~~E1");
                    if (a[n].op==4)
                        {
                            b[++m].op=0; b[m].id=int(x);
                            b[++m].op=1; b[m].id=n;

                        }
                }
            ss=s2; while (*ss==' ') ss++;
            s2=ss;
            tmp=0;x=0;
            while (*s2>='0'&&*s2<='9'){tmp++;if (tmp<10)x=x*10+(*s2)-'0';s2++;}
            if (a[n].op==4)
                {   if (tmp<10)
                    a[n].tim=x;else puts("~~~~~~~~~E2");
                }
        }
    if (!dieflag) {ret();return re;}
    b[++m].op=0; b[m].id=0;
    b[++m].op=1; b[m].id=n+1;
    fun[n+1]=0;
    a[0].op=3; a[n+1].op=4;a[n+1].tim=1000000000;
    sort(b+1,b+m+1);
    while (!st2.empty()) st2.pop();

    int last=0,lastop=-1,l,r;
    ce=0,sz=0;
    ms(cen,255);
    //------------------------------------
    fr(i,1,m)
    {
        if (b[i].op==0)
        {   if (lastop==1)  last++;
            if (last<b[i].id) {           aa[sz]=(last);
                                          bb[sz]=(b[i].id-1);
                                          cc[sz]=(ce);
                                          sz++;
                              }
            ce++;
            last=b[i].id;
            lastop=b[i].op;
            continue;
        }
        if (lastop==1)
            {
                nown=0;all=0;
                int j_min=sz;
                for (int j=sz-1;j>=0;j--)if (ce==cc[j])j_min=j;else break;

                fr(j,j_min,sz-1)       fr(k,aa[j],bb[j]) id[k]=++nown;
                if (last+1<=b[i].id)   fr(k,last+1,b[i].id) id[k]=++nown;
            
                o=0;fr(j,1,nown)head[j]=-1,typ[j]=0;
                l=last+1,r=b[i].id;ggg(l,r);

                int mm=last+1;
                ll mmm=st2.top();st2.pop();
                while (cc[sz-1]==ce)
                    {
                        l=aa[sz-1];r=bb[sz-1];
                        ggg(l,r);
                        sz--;
                        add(id[r],id[mm],mmm+fun[mm]);
                        mm=l;
                    }
                r=b[i].id;
                all+=fun[l];if (!spfa_getans(nown,fun[l])){ret();;return re;}
                ll tmp=d[nown]*a[r].tim;
                if (tmp>maxans){ret();;return re;}
                st2.push(tmp);last=b[i].id;lastop=b[i].op;
                ce--;
                continue;
            }
        ce--;
        l=last,r=b[i].id;
        nown=0; all=0;
        fr(j,l,r)id[j]=++nown;
        o=0;fr(j,1,nown)head[j]=-1,typ[j]=0;
        ggg(l,r);
        all+=fun[l]; if (!spfa_getans(nown,fun[l])){ret();;return re;}
        ll tmp=d[nown]*a[r].tim;
        if (tmp>maxans){ret();;return re;}
        st2.push(tmp);last=b[i].id;lastop=b[i].op;
    }
    if (ans3310>maxans){ret();;return re;}
    printf("%lld\n",ans3310);
    fun[n+1]=1;//fun[n+1]=int(log(n+1)/log(10)+1e-9)+1;
    return re;
}
int main()
{  
    fun[0]=0;
    fr(i,1,100000) fun[i]=1;//fun[i]=int(log(i)/log(10)+1e-9)+1;
    idd=0;
    while (doit());
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值