1. 程式人生 > 其它 >利用Burp Suite對OWASP Juice Shop進行滲透測試

利用Burp Suite對OWASP Juice Shop進行滲透測試

演算法介紹:

  SPFA(Shortest Path Faster Algorithm)是Bellman-Ford演算法的一種佇列實現,減少了不必要的冗餘計算。

演算法流程:

   演算法大致流程是用一個佇列來進行維護。 初始時將源加入佇列。 每次從佇列中取出一個元素,並對所有與他相鄰的點進行鬆弛,若某個相鄰的點鬆弛成功,則將其入隊。 直到佇列為空時演算法結束。
維護一個佇列,裡面存放所有需要進行迭代的點。初始時佇列中只有一個點S。用一個布林陣列記錄每個點是否處在佇列中。

每次迭代,取出隊頭的點v,依次列舉從v出發的邊v->u,設邊的長度為len,判斷Dist[v]+len是否小於Dist[u],若小於則改進Dist[u],將Fa[u]記為v,並且由於S到u的最短距離變小了,有可能u可以改進其它的點,所以若u不在佇列中,就將它放入隊尾。這樣一直迭代下去直到佇列變空,也就是S到所有的最短距離都確定下來,結束演算法。

若一個點入隊次數超過n,則有負權環。

//P2850Wormholes G如果農場裡有負環則一定可以穿越回出發時刻之前
#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
using namespace std;
const int maxm=3000*2+5,maxn=500+5;
struct Edge{
    int to,next,dis;
}e[maxm];
int F,n,m,W,len,head[maxn];
void Insert(int x,int y,int dis){
    e[++len].to=y;
    e[len].dis=dis;
    e[len].next=head[x];
    head[x]=len;
}
int d[maxn];//d[i]i到st的最短距離
int cnt[maxn];//cnt[i]i入隊的次數,如果超過maxk則說明有負環
bool vis[maxn];//用於記錄有沒有在佇列裡
bool spfa(int st){
    for(int i=1;i<=n;++i)d[i]=0x3f3f3f3f;
    for(int i=1;i<=n;++i)cnt[i]=0;
    memset(vis,0,sizeof(vis));
    queue<int>q;
    q.push(st);
    cnt[st]++;
    d[st]=0;
    vis[st]=1;
    while(!q.empty()){
        int x=q.front();
        q.pop();
        vis[x]=0;
        for(int i=head[x];i;i=e[i].next){
            int v=e[i].to;
            if(d[v]>d[x]+e[i].dis){
                d[v]=d[x]+e[i].dis;
                if(!vis[v]){//如果x可以更新v 則v入隊
                   q.push(v);vis[v]=1;
                   cnt[v]++;
                   if(cnt[v]>n){
                       return 1;
                    }
                }
            }
        }
    }
    return 0;
}
void work(){
    scanf("%d%d%d",&n,&m,&W);
    int st=0;len=0;
    memset(head,0,sizeof(head));
    for(int i=1;i<=m;++i){
        int x,y,dis;
        if(!st)st=x;
        scanf("%d%d%d",&x,&y,&dis);
        Insert(x,y,dis);Insert(y,x,dis);
    }
    for(int i=1;i<=W;++i){//處理蟲洞
        int x,y,dis;
        scanf("%d%d%d",&x,&y,&dis);
        Insert(x,y,-dis);
    }
    if(spfa(1)){
        printf("YES\n");
    }
    else {
        printf("NO\n");
    }
}
int main(){
    scanf("%d",&F);
    while(F--)
    work();
    return 0;
}

SPFA 在形式上和寬度優先搜尋非常類似,不同的是寬度優先搜尋中一個點出了佇列就不可能重新進入佇列,但是SPFA中一個點可能在出佇列之後再次被放入佇列,也就是一個點改進過其它的點之後,過了一段時間可能本身被改進,於是再次用來改進其它的點,這樣反覆迭代下去。設一個點用來作為迭代點對其它點進行改進的平均次數為k,有辦法證明對於通常的情況,k在2左右。

在實際的應用中SPFA的演算法時間效率不是很穩定,為了避免最壞情況的出現,通常使用效率更加穩定的Dijkstra演算法。

https://www.cnblogs.com/Jason-Damon/p/3787756.html

update2022.1.16

關於堆優化dijistra不能求最長路,spfa詐屍

dijistra本身基於貪心思想,如果是最短路,區域性的最優解 一定是全域性最優解的一部分,而最長路不一樣,區域性最優解不一定是全域性最優解。

求最長路還是要用spfa(改成負邊權跑最短路),由於spfa可以反覆更新,可以保證答案的正確性,但願最長路不會卡spfa