BZOJ 1486: [HNOI2009]最小圈 分數規劃

時空隧道


分析:
其實就分數規劃來講這道題很簡單….
重點是判負環…
一般的spfa判負環一定會TLE,看看數據範圍就知道了…
怎麼辦呢…可以dfs判負環,但是還是會TLE…
怎麼辦啊…
有一個機智的辦法,反正我們都是判負環,爲什麼還要把dis賦成inf呢,乾脆賦成0好了…正確是顯然的…時間複雜度呢…遞歸層數減少了…只有變成負數的時候纔會去遞歸…所以從10sTLE變成了128msAC…


代碼如下:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
//by NeighThorn
#define inf 100000000000
using namespace std;
//長眉連娟,微睇綿藐,色授魂與,心愉於側 
const int maxn=3000+5,maxm=10000+5;
int n,m,hd[maxn],to[maxm],nxt[maxm],vis[maxn],tim[maxn],cnt;
double w[maxm],sum,dis[maxn]; 

inline void add(double s,int x,int y){
    w[cnt]=s;to[cnt]=y;nxt[cnt]=hd[x];hd[x]=cnt++;
}

inline bool dfs(int root,double mid){
    vis[root]=1;
    for(int i=hd[root];i!=-1;i=nxt[i])  
        if(dis[to[i]]>dis[root]+w[i]-mid){
            if(vis[to[i]])
                return true;
            dis[to[i]]=dis[root]+w[i]-mid;
            if(dfs(to[i],mid))
                return true;
        }
    vis[root]=0;
    return false;
}

inline bool check(double mid){
    memset(vis,0,sizeof(vis));
    memset(dis,0,sizeof(dis));
    for(int i=1;i<=n;i++)
        if(dfs(i,mid))
            return true;
    return false;
}

signed main(void){
    memset(hd,-1,sizeof(hd));
    scanf("%d%d",&n,&m);
    double s;cnt=sum=0;
    for(int i=1,x,y;i<=m;i++)
        scanf("%d%d%lf",&x,&y,&s),add(s,x,y),sum+=s;
    double l=-inf,r=inf,ans;
    while(r-l>=1e-9){
        double mid=(l+r)/2.0;
        if(check(mid))
            r=mid,ans=mid;
        else
            l=mid;
    }
    printf("%.8f\n",ans);
    return 0;
}

by >_< NeighThorn

發佈了170 篇原創文章 · 獲贊 5 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章