BZOJ3597: [Scoi2014]方伯伯运椰子

1.jpg
2.jpg
3.jpg

输入格式:

第1 行包含2 个整数n,m
接下来m 行代表m 条边,表示这个交通网络。
每行6 个整数,表示ui,vi,ai,bi,ci,di.
接下来1 行包含1 条边,表示连接起点的边

输出格式:

一个浮点数,保留2 位小数,表示要求的答案,数据保证答案大于0

样例输入:

6 7
1 2 0 0 1 1000
2 4 0 0 1 1000
4 6 0 0 1 1000
1 3 0 0 0 0
3 5 0 0 0 0
5 6 0 0 0 0
6 8 0 0 1 0
7 1 0 0 1 0

样例输出:

500.00

数据范围:

4.jpg

时间限制:

3s

空间限制:

64M
具体思路:要求的答案好奇怪啊,好像很像分数规划啊
那么就用分数规划做吧
根据套路,我们要二分一下答案
然后怎么办办勒
 
发现由于原图是满流的,所以最优方案一定是从一个点到另一个点的一条路径+1流量,另一条-1流量
那么对于流量>0的边,可以加流量,那就连一条长为单位流量+加流量需要的代价,也可以减流量那就连一条长为-单位流量+减流量需要的代价的反向边
对于流量为0的边,就只可以加流量了
然后把每个边的长+mid(二分的答案)然后SPFA判一下有无负环就好了
 
AC代码:
复制代码
#include<bits/stdc++.h>
#define INF 100000000
const double eps=1e-6;
using namespace std;
int x,y,n,m,i,j,top=1,A,B,C,D,first[200000],next[200000],last[200000],to[200000];
int bo[200000];
double dis[200000],len[200000],ans;
void add(int x,int y,int l)
{
    top++,to[top]=y,len[top]=(double)l;
    if(first[x]==0)first[x]=top;else next[last[x]]=top;
    last[x]=top;
}
void SPFA(int x,double mid)
{
    if(ans)return;
    bo[x]=true;
    for(int i=first[x];i;i=next[i])
    if(dis[x]+len[i]+mid<dis[to[i]])
    {
        if(bo[to[i]]||ans)
        {
            ans=1;
            break;
        }
        dis[to[i]]=dis[x]+len[i]+mid;
        SPFA(to[i],mid);
    }
    if(ans)return;
    bo[x]=false;
}
bool ok(double mid)
{
    for(int i=1;i<=n+2;i++)dis[i]=0.0,bo[i]=0;
    for(int i=1;i<=n+2;i++)
    {
        ans=0;SPFA(i,mid);
        if(ans)return true;
    }
    return false;
}
int main()
{
    scanf("%d%d",&n,&m);
    for(i=1;i<=m+1;i++)
    {
        scanf("%d%d%d%d%d%d",&x,&y,&A,&B,&C,&D);
        if(C)add(x,y,D+B),add(y,x,A-D);else add(x,y,B+D);
    }
    
    double l=0,r=1000.0,mid;
    while(r-l>eps)
    {
        mid=(l+r)/2.0;
        if(ok(mid))l=mid;else r=mid;
    }
    printf("%.2lf",mid);
}
原文地址:https://www.cnblogs.com/Orange-User/p/8531223.html