SPFA模板+dfs版检测负环

const int MAXN=1e4+10;
int m,n,s,cnt,head[MAXN],dist[MAXN];
struct Edge {
    int to,val,next;
} e[500010];

inline void add(int x,int y,int val) {
    e[++cnt].to=y;
    e[cnt].val=val;
    e[cnt].next=head[x];
    head[x]=cnt;
}
bool inque[MAXN];
queue<int>que;
inline bool SPFA() {
    memset(dist,0x3f3f3f3f,sizeof(dist));
    memset(inque,0,sizeof(inque));
    dist[s]=0;
    inque[s]=1;
    que.push(s);
    while(!que.empty()) {
        int x=que.front();
        que.pop();
        inque[x]=0;
        for(int i=head[x]; i; i=e[i].next) {
            int y=e[i].to;
            if(e[i].val+dist[x]<dist[y]) {
                dist[y]=e[i].val+dist[x];
                if(!inque[y]) {
                    inque[y]=1;
                    que.push(y);
                }
            }
        }
    }
    return 1;
}
int main() {
    read(n),read(m),read(s);
    int x,y,val;
    while(m--) {
        read(x),read(y),read(val);
        add(x,y,val);
    }
    SPFA();
    for(int i=1; i<=n; ++i) {
        if(dist[i]!=0x3f3f3f3f)
            printf("%d ",dist[i]);
        else
            printf("2147483647 ");
    }
    return 0;
}

检测负环(dfs dpfa)

题目链接
题意 给定一张图,每个顶点有一个快乐值,每条边有一个长度,选择一个环使得总快乐值/总长最大。
输入

5 7
30
10
10
5
10
1 2 3
2 3 2
3 4 5
3 5 2
4 5 5
5 1 3
5 2 2

输出:

6.00

二分答案
更改边的权重\(w[i]\)=目标节点快乐值\(-\)边长*可能的答案,如果出现正环,则有答案,且该可能的答案太小了即,将\(-w\)作为真正的权值,检测是否有负环。

#include<bits/stdc++.h>
#include<queue>
#include<iostream>
#include<cstring>
using namespace std;
char buf[1<<17],*L=buf,*R=buf;
inline char gc() {
    return L==R&&(R=(L=buf)+fread(buf,1,1<<17,stdin),L==R)?EOF:*L++;
}
template<typename T>
inline void read(T&x) {
    int flag=x=0;
    char ch=gc();
    while (ch<'0'||ch>'9')
        flag|=ch=='-',ch=gc();
    while (ch>='0'&&ch<='9')
        x=(x<<3)+(x<<1)+ch-48,ch=gc();
    if(flag)
        x=-x;
}
#define Memset(arr,val) memset(arr,val,sizeof(arr))
const int MAXN=1e4+10;
int k[MAXN],cnt,head[MAXN];
int n,m;
struct edge {
    int to,len,next;
} e[MAXN*5];
inline void add(int x,int y,int len) {
    e[++cnt].len=len;
    e[cnt].next=head[x];
    e[cnt].to=y;
    head[x]=cnt;
}
double dis[MAXN],w[MAXN];
bool vis[MAXN];
int num[MAXN];
inline bool spfa(int x) {
    vis[x]=1;
    for(int i=head[x]; i; i=e[i].next) {
        int y=e[i].to;
        if(dis[y]>dis[x]-w[i]) {
            dis[y]=dis[x]-w[i];
            if(vis[y]||spfa(y)) {
                vis[y]=0;
                return 1;
            }
        }
    }
    return vis[x]=0;
}
inline bool check() {
    Memset(dis,0);//因为不是求距离,所以随便初始化就ok了
    Memset(vis,0);
    for(int i=1; i<=n; ++i)
        if(spfa(i))
            return 1;
    return 0;
}
int main() {
    read(n),read(m);
    for(int i=1; i<=n; ++i)
        read(k[i]);
    int x,y,len;
    while(m--) {
        read(x),read(y),read(len);
        add(x,y,len);
    }
    double l=1,r=1001;
    while(l+1e-5<r) {
        double mid=(r+l)/2;
        for(int i=1;i<=cnt;++i)w[i]=1.0*k[e[i].to]-e[i].len*mid;
        if(check())
            l=mid+1e-5;
        else
            r=mid-1e-5;
    }
    printf("%.2lf",r);
    return 0;
}
posted @ 2020-12-16 17:22  肆之月  阅读(113)  评论(0编辑  收藏  举报