Sightseeing Cows POJ

来源:互联网 发布:java异常两大类 编辑:程序博客网 时间:2024/06/08 02:51

大致题意
给出一个有向图,每个点都有一个点权,每条有向边也都有一个边权,要求出一个环使得环中点权之和与边权之和的比值最大。
思路:
如果将环上的边和点一一绑定,E(u,v)=k(e(u,v))-value[u],这样就变成选取一个合适的k;
考虑k_max是答案,然后发现k >k_max不可能有负环,而k

/* * Author       :  Echo * Email        :  1666424499@qq.com   * Description  :    * Created Time :  2017/10/6 18:08:21 * Last Modify  :  2017/10/6 20:48:35 * File Name    :  a.cpp */#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <algorithm>#include <string>#include <vector>#include <stack>#include <queue>#include <set>#include <time.h>#define LL long long#define mem(a,k) memset(a,k,sizeof(a))#include <map>using namespace std;const int maxint = -1u>>1;const int maxn=1e3+100;const int maxm=1e4+100;struct edge{    int to,next;    double value;    void set(int a,double b,int c){         to=a,value=b,next=c;    }}bn[maxm];int head[maxn],cnt=0;void addedge(int u,int v,double value){    bn[cnt].set(v,value,head[u]);    head[u]=cnt++;}int an[maxn];double dis[maxn];bool vis[maxn];int in[maxn];int spfa(double a,int n){    for(int i=1;i<=n;i++){        vis[i]=0;    }    queue<int>que;    while(!que.empty())que.pop();    for(int i=1;i<=n;i++){        vis[i]=1;        dis[i]=0;        in[i]=1;        que.push(i);    }    while(!que.empty()){        int u=que.front();        que.pop();        vis[u]=0;        for(int i=head[u];i!=-1;i=bn[i].next){            int v=bn[i].to;            double value=a*bn[i].value-an[u];            if(dis[v]>dis[u]+value){                dis[v]=dis[u]+value;                if(!vis[v]){                    que.push(v);                    vis[v]=1;                    in[v]++;                    if(in[v]>n) return 1;                }            }        }    }    return 0;}int main(){    int n,m;    cin>>n>>m;    for(int i=1;i<=n;i++)        head[i]=-1;    cnt=1;    for(int i=1;i<=n;i++) scanf("%d",&an[i]);    for(int i=1;i<=m;i++){        int a,b;        double value;        scanf("%d%d%lf",&a,&b,&value);        addedge(a,b,value);    }    double l=0,r=2000,mid=(l+r)/2;    while(r-l>1e-3){        mid=(l+r)/2;        if(spfa(mid,n)){            l=mid;        }        else r=mid;    }    printf("%.2f\n",mid);    return 0;}/*5 73010105101 2 32 3 23 4 53 5 24 5 55 1 35 2 26.00 */