zoukankan      html  css  js  c++  java
  • BZOJ 1486 最小圈(01分数规划)

    好像是很normal的01分数规划题。最小比率生成环。

    u(c)=sigma(E)/k。转化一下就是k*u(c)=sigma(E). sigma(E-u(c))=0.

    所以答案对于这个式子是有单调性的,二分答案,判断sigma(E-ans)是否小于0,实际上就是寻找图是否有负环。

    但是此题用标准的spfa找负环会超时。

    需要用到dfs优化的spfa。

    既然我们只需要判断负环,那么就相当于我们需要找到一条权值和为负的回路。 
    既然我们只需要找到权值和为负的回路,那不妨使距离数组d初始化为0。 
    这样处理后,第一次拓展只会拓展到与起点相连边权为负的边。 
    那么我们就分别枚举所有的点作为起点,如果已经找到一个负环就不再继续枚举。 
    根据SPFA,我们找到的负环一定包含当前枚举的这个点。(因为这个点出现了两次啊) 
    正确性相当的显然。

    # include <cstdio>
    # include <cstring>
    # include <cstdlib>
    # include <iostream>
    # include <vector>
    # include <queue>
    # include <stack>
    # include <map>
    # include <set>
    # include <cmath>
    # include <algorithm>
    using namespace std;
    # define lowbit(x) ((x)&(-x))
    # define pi 3.1415926535
    # define eps 1e-9
    # define MOD 100000007
    # define INF 1000000000
    # define mem(a,b) memset(a,b,sizeof(a))
    # define FOR(i,a,n) for(int i=a; i<=n; ++i)
    # define FO(i,a,n) for(int i=a; i<n; ++i)
    # define bug puts("H");
    # define lch p<<1,l,mid
    # define rch p<<1|1,mid+1,r
    # define mp make_pair
    # define pb push_back
    typedef pair<int,int> PII;
    typedef vector<int> VI;
    # pragma comment(linker, "/STACK:1024000000,1024000000")
    typedef long long LL;
    int Scan() {
        int res=0, flag=0;
        char ch;
        if((ch=getchar())=='-') flag=1;
        else if(ch>='0'&&ch<='9') res=ch-'0';
        while((ch=getchar())>='0'&&ch<='9')  res=res*10+(ch-'0');
        return flag?-res:res;
    }
    void Out(int a) {
        if(a<0) {putchar('-'); a=-a;}
        if(a>=10) Out(a/10);
        putchar(a%10+'0');
    }
    const int N=3005;
    //Code begin...
    
    struct Edge{int p, next; double cost, w;}edge[20005];
    int head[N], cnt=1, n, m;
    double dis[N];
    bool vis[N], flag;
    
    void add_edge(int u, int v, int w){
        edge[cnt].p=v; edge[cnt].next=head[u]; edge[cnt].w=w; head[u]=cnt++;
    }
    void DFS_SPFA(int u){
        if(flag) return ;
        vis[u]=true;
        for(int i=head[u]; i; i=edge[i].next) {
            if(flag) return ;
            int v=edge[i].p;
            if(dis[u]+edge[i].cost<dis[v]) {
                dis[v]=dis[u]+edge[i].cost;
                if(vis[v]){flag=true; return ;}
                else DFS_SPFA(v);
            }
        }
        vis[u]=false;
    }
    bool check(double x){
        FOR(i,1,m) edge[i].cost=edge[i].w-x;
        FOR(i,1,n) dis[i]=0, vis[i]=0;
        flag=false;
        FOR(i,1,n) {
            DFS_SPFA(i);
            if (flag) return true;
        }
        return false;
    }
    int main ()
    {
        int u, v;
        double w;
        scanf("%d%d",&n,&m);
        FOR(i,1,m) scanf("%d%d%lf",&u,&v,&w), add_edge(u,v,w);
        double l=-10000001, r=10000001, mid;
        FOR(i,1,100) {
            mid=(l+r)/2;
            if (check(mid)) r=mid;
            else l=mid;
        }
        printf("%.8lf
    ",l);
        return 0;
    }
    View Code
  • 相关阅读:
    FFmpeg笔记-基本使用
    记一次下载大文件存在数据异常问题排查
    从零开始编写IntelliJ IDEA插件
    Guava LoadingCache不能缓存null值
    FFmpeg笔记--vcodec和-c:v,-acodec和-c:a的区别?
    说说maven依赖冲突,依赖调解,依赖传递和依赖范围
    记一次NoHttpResponseException问题排查
    JVM源码分析-类加载场景实例分析
    JVM源码分析-JVM源码编译与调试
    理解PHP的变量,值与引用的关系
  • 原文地址:https://www.cnblogs.com/lishiyao/p/6589563.html
Copyright © 2011-2022 走看看