• 【题解】cycle


    【题解】cycle

    题目描述

    给定一个无向图,求一个环,使得环内边权(div)环内点数最大。

    数据范围

    (n le 5000) (mle 10000)

    (Solution)

    考虑到我们可以对答案的式子变一下形,

    (frac{Sigma_{iin V'} w_i}{|V'|}le ans)

    (Sigma_{iin V'}w_i-ans imes |V'|le0)

    这一步不要看不懂了((i)共有(|V'|)个,所以(ans)仍然总共被加了(|V'|)次):

    (Sigma_{iin V'} (w_i-ans) le 0)

    (Sigma_{i in V'} w'_ile0)

    直接(spfa)跑负环就好了。

    实际上这是一个很有用的方法,先根据题目答案的意义判断是否存在答案单调性,再通过数学变换得到我们想要的式子。

    或者感性理解,我们得到一堆边的平均边权是(ans)了,那么这个边集的所有权减去这个(ans)然后加起来一定等于(0)。假如加起来比(0)大,说明不存在,假设比这个小,说明有更优解。

    上好看的代码qvq

    #include<bits/stdc++.h>
    
    using namespace std;typedef long long ll;
    #define DRP(t,a,b) for(register int t=(a),edd=(b);t>=edd;--t)
    #define RP(t,a,b)  for(register int t=(a),edd=(b);t<=edd;++t)
    #define ERP(t,a)   for(register int t=head[a];t;t=e[t].nx)
    #define midd register int mid=(l+r)>>1
    #define TMP template < class ccf >
    TMP inline ccf qr(ccf b){
        register char c=getchar();register int q=1;register ccf x=0;
        while(c<48||c>57)q=c==45?-1:q,c=getchar();
        while(c>=48&&c<=57)x=x*10+c-48,c=getchar();
        return q==-1?-x:x;}
    TMP inline ccf Max(ccf a,ccf b){return a<b?b:a;}
    TMP inline ccf Min(ccf a,ccf b){return a<b?a:b;}
    TMP inline ccf Max(ccf a,ccf b,ccf c){return Max(a,Max(b,c));}
    TMP inline ccf Min(ccf a,ccf b,ccf c){return Min(a,Min(b,c));}
    TMP inline ccf READ(ccf* _arr,int _n){RP(t,1,_n)_arr[t]=qr((ccf)1);}
    //----------------------template&IO---------------------------
    
    const int maxn=3e3+15;
    const int maxm=1e4+15;
    struct E{
        int to,nx;
        long double w;
    }e[maxm];
    const long double EPS=1e-10;
    int head[maxn];
    int usd[maxn];
    bool in[maxn];
    double d[maxn];
    double sa[maxm];
    int cnt;
    int n,m;
    inline void add(int fr,int to,long double w){
        cnt++;
        e[cnt].to=to;
        e[cnt].nx=head[fr];
        e[cnt].w=w;
        sa[cnt]=w;
        head[fr]=cnt;
    }
    bool c=0;
    void spfa(int now){
        if(c) return;
        usd[now]=1;
        ERP(t,now){
            if(d[e[t].to]>d[now]+e[t].w){
                d[e[t].to]=d[now]+e[t].w;
                if(c||usd[e[t].to]) return void(c=1);
                spfa(e[t].to);
            }
        }
        usd[now]=0;
    }
    
    inline bool chek(long double x){
        RP(t,1,m) e[t].w=sa[t]-x;
        RP(t,1,n) usd[t]=d[t]=0;c=0;
        RP(t,1,n) if(!usd[t]) spfa(t);
        return c;
    }
    
    
    int main(){
        n=qr(1);m=qr(1);
        int t1,t2;
        long double t3;
        long double l=-1e7-(long double)1,r=1e7+(long double)1;
        long double mid;
        RP(t,1,m){
            t1=qr(1);t2=qr(1);
            scanf("%Lf",&t3);
            add(t1,t2,t3);
        }
        do{
            mid=(l+r)/(long double)2;
            if(chek(mid))
                r=mid;
            else
                l=mid;
        }while(l+EPS<r);
        printf("%.8Lf
    ",l);
        return 0;
    }
    
    /*
      dfs序+树连剖腹
      乱做
      orz yyb
    
      不行 有情况没有考虑到!
      直接tarjin
    
      二分就好了吧 乱做OK
    
      不行 我是****
    */
    
    
  • 相关阅读:
    【转】Linux进程间通信——管道及有名管道
    【转】linux进程间通信——信号(上)
    【转】Linux进程间通信—— 共享内存(下)
    【转】linux进程间通信——信号(下)
    python 文件
    文本分类入门(转)
    五大主流数据库模型 (转)
    使用libSVM
    Python编程之前戏——Python环境搭建与编译器的选择 Java(转)
    最棒的10款MySQL GUI工具 (转)
  • 原文地址:https://www.cnblogs.com/winlere/p/10367960.html
Copyright © 2020-2023  润新知