zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Android 监听键盘的弹起与收缩
    Android Glide+CircleImageView实现加载圆形图片列表
    Java 集合
    Java 文件IO续
    Java 文件IO
    Java 网络编程
    Android AIDL Service
    Android 四大组件之Service
    Android 开源项目分类汇总(转)
    Android SQLite数据库
  • 原文地址:https://www.cnblogs.com/foursmonth/p/14145068.html
Copyright © 2011-2022 走看看