首页 > 其他 > 详细

sgu-236 Greedy Path

时间:2015-03-11 23:28:26      阅读:343      评论:0      收藏:0      [点我收藏+]

题目大意:
给你一个N个点,M条边的有向图G,每一条边有两个属性:cost,time。然后要你求出一个环T使得Σcost[u]/Σtime[v](u,vT)最大。

解题思路:
我们要求最大值,一个很直观的思路就是二分答案,然后那么题目就变为询问是否存在一个环T使得使得Σcost[u]/Σtime[v](u,vT)>=k
整理有:0>=k?Σtime[v]?Σcost[u](u,vT) -> 0>=Σ(k?time[v]?cost[v])(vT)
易发现这就是spfa判负环的条件,然后就很简单了吧!!!

AC代码:

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iostream>
#include <algorithm>
#include <queue>
#include <vector>

using namespace std;

struct bian_
{
    int num;
    double cost,times;
    int next;
}bian[10000]={{0,0,0,0}};
int First[52]={0};
int n,m;
int father[52]={0};
double dist[52]={0};
int hash[52]={0};
int Times[52]={0};

inline void Add(int p,int q,double u,double v,int k)
{
    bian[k].next=First[p];
    bian[k].num=q;
    bian[k].cost=u;
    bian[k].times=v;
    First[p]=k;
    return;
}

inline int check(double k)
{
    queue <int> Queue;
    for(;!Queue.empty();) Queue.pop();
    for(int i=1;i<=n;i++)
        dist[i]=1e9;
    dist[1]=0;
    Queue.push(1);
    memset(hash,0,sizeof(hash));
    hash[1]=1;
    memset(father,0,sizeof(father));
    memset(Times,0,sizeof(Times));
    Times[1]++;
    for(;!Queue.empty();)
    {
        int u=Queue.front();
        Queue.pop();
        if(Times[u]>n+1)
            return u;
        for(int p=First[u];p!=0;p=bian[p].next)
        {
            int v=bian[p].num;
            double d=(double)bian[p].times*k-bian[p].cost;
            if(dist[u]+d<dist[v])
            {
                father[v]=u;
                dist[v]=dist[u]+d;
                if(hash[v]==0)
                {
                    hash[v]=1;
                    Queue.push(v);
                    Times[v]++;
                }

            }
        }
        hash[u]=0;
    }
    return 0;
}

int main()
{
    scanf("%d%d",&n,&m);
    double L=1e-10,R=101;
    for(int i=1;i<=m;i++)
    {
        int p,q;
        double u,v;
        scanf("%d%d%lf%lf",&p,&q,&u,&v);
        Add(p,q,u,v,i);
    }

    for(;L+1e-10<=R;)
    {
        double mid=(L+R)/2;
        if(check(mid))
            L=mid;
        else R=mid;
    }

    vector <int> V; 
    int st=check(L);

    if(st==0)
    {
        printf("0\n");
        return 0;
    }

    memset(hash,0,sizeof(hash));

    for(;hash[st]<=1;st=father[st])
    {
        hash[st]++;
        if(hash[st]==2)
            V.push_back(st);
    }

    printf("%d\n",V.size());

    for(int i=V.size()-1;i>=0;i--)
        printf("%d ",V[i]);

    puts("");
    return 0;
}

sgu-236 Greedy Path

原文:http://blog.csdn.net/qq_21995319/article/details/44206509

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!