bzoj3597: [Scoi2014]方伯伯运椰子(01分数规划)

传送门
题意咕咕咕有点麻烦不想写


思路:
考虑加了多少一定要压缩多少,这样可以改造边。
于是可以通过分数规划+ s p f a spfa spfa解决。
代码:

#include
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
    static char buf[rlen],*ib,*ob;
    (ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
    return ib==ob?-1:*ib++;
}
inline int read(){
    int ans=0;
    char ch=gc();
    while(!isdigit(ch))ch=gc();
    while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
    return ans;
}
const int N=10005,M=15005;
const double eps=1e-3;
typedef pair<int,double> pii;
vector<pii>e[N];
int n,m;
bool in[N];
double dis[N];
inline bool dfs(int p){
    in[p]=1;
    for(ri i=0,v;i<e[p].size();++i){
        if(dis[v=e[p][i].fi]>dis[p]+e[p][i].se){
            if(dis[v]=dis[p]+e[p][i].se,in[v])return 1;
            if(dfs(v))return 1;
        }
    }
    return in[p]=0;
}
inline bool check(double tmp){
    for(ri i=1;i<=n+2;++i){
        for(ri j=0;j<e[i].size();++j)e[i][j].se+=tmp;
        dis[i]=0,in[i]=0;
    }
    bool ret=0;
    for(ri i=1;i<=n+2;++i)if(dfs(i)){ret=1;break;}
    for(ri i=1;i<=n+2;++i)for(ri j=0;j<e[i].size();++j)e[i][j].se-=tmp;
    return ret;
}
int main(){
    n=read();
    for(ri tt=read(),u,v,a,b,c,d;tt;--tt){
        u=read(),v=read(),a=read(),b=read(),c=read(),d=read();
        e[u].push_back(pii(v,b+d));
        if(c)e[v].push_back(pii(u,a-d));
    }
    double l=0,r=1000;
    while(r-l>=eps){
        double mid=(l+r)/2;
        if(check(mid))l=mid;
        else r=mid;
    }
    printf("%.2lf",l);
    return 0;
}

你可能感兴趣的:(#,01分数规划,#,spfa)