【勤劳的小熊】解题报告

//tyvj1609

背景 Background	
	AndyBear 生日模拟赛 第三题
		
		
	描述 Description	
	小熊BIBO要去给熊姥姥送蜂蜜。在去姥姥家的路上,要经过若干个村庄,村庄和村庄之间有小路相连,每条路都有不同的通过时间。每个村庄里都有很多好玩的东西,比如熊大叔的玩具店,还有兔大嫂的游乐城,所以每个村庄都对BIBO有一个吸引值F,如果小熊BIBO经过的某个村庄的吸引值太大,她就有可能留在那不走了! 现在,小熊BIBO希望在不超过T的时间内到达姥姥家,她想知道,在满足路上时间不超过T的情况下,路过的村庄的最大的吸引值最小是多少?
		
		
	输入格式 Input Format	
	输入文件的第一行,有5个数字,n,m,u,v,T。 代表有n个村庄,m条双向小路,小熊BIBO要从u前往v,时间限制为T。
接下来的n行,每行1个数字,表示第i个村庄的吸引值为Fi。
接下来的m行,每行3个数字,x,y,c。表示有一条双向小路,连接的是x和y,需要的通过时间为c。
		
		
	输出格式 Output Format	
	输出仅包含一个数字,表示从u到v,在时间不超过T的情况下,所经过的城市的最大吸引值最小是多少。
如果不能到达,请输出-1
		
		
	样例输入 Sample Input [复制数据]	
	4 4 2 3 8856102 1 22 4 11 3 43 4 3
		
		
	样例输出 Sample Output [复制数据]	
	8解释: 2->1->3. 其中城市1的吸引值最大,为8.
		
		
	时间限制 Time Limitation	
	各个测试点1s
		
		
	注释 Hint	
	对于60%的数据,满足n<=200,m<=10000,T<=200
对于100%的数据,满足n<=10000,m<=50000,T<=10^9
对于100%的数据,满足0<=ci,fi<=10^9,输入数据有重边。



弄死过不到,汪维正的建图的艺术里面的例题。

没有难度。二分,spfa,前向星,slf,就这些知识点。

和以前的一道收费站问题一模一样。


注意点:

1、边表排序的时候,首先以from,再以value排序。(后面这点主要是为了避免有重边的情况,使点多次入队)

2、不确定边的正负的时候最好用spfa

3、slf要注意队列l、r都为0的情况

4、二分解空间的时候,要注意减少解空间。(如此题,既然解是attract值中的一个,就不应将二分空间扩大了)


/*                                                        *\

WA20    二分右边界sum是吸引值总和,错算成是时间总和
    没有判断 
        没有判断起点和终点吸引度是否大于二分mid值 
        无向图边的数量没有加倍
        无解时没有输出-1 
WA70    数据范围是10^9,用long long。
WA20    long long不能用printf和scanf 
WA70    改的时候改错了,把-1改错成ans了 
        又加了一个SLF优化 
TL        原来错的那组超时了
WA90    发现二分写错了,应该二分attract值,
        而不是二分答案,超时的那组又错了     
\*                                                        */


#include <cstdio>
#include <iostream>
#include <cstdlib>

struct ftv
{
    long f;
    long t;
    long long v;
};

long n;long m;long u;long v;long long t;
long f[10002];
long long attract[10002];
const long long oo = 0x7fffffffff000000ll;

ftv bian[50002];
long top = 0;
long long sum = 0;
long que[10000000];
long long dist[10002];
bool used[10002];

void insert(long x,long y,long long c)
{
    top++;
    bian[top].f = x;
    bian[top].t = y;
    bian[top].v = c;
}

int bigger(const void* a,const void* b)
{
    ftv* aa = (ftv*)a;
    ftv* bb = (ftv*)b;
    long aaa = aa->f;
    long bbb = bb->f;
    if (aaa>bbb)
    {
        return 1;
    }
    else if (aaa==bbb)
    {
        return 0;
    }
    else
        return -1;
}

bool can(long long mid)
{
    if (attract[v]>mid||attract[u]>mid)
        return false;
    //排除不可能的值 
    long long l=0;long long r=0;
    for (long i=1;i<n+1;i++)
    {
        dist[i] = oo;
    }
    /*
    for (long i=f[u];i<m+1;i++)
    {
        if (bian[i].f != u)
            break;
        if (attract[bian[i].t]<=mid&&bian[i].v<=t)
            dist[bian[i].t] = bian[i].v;
    }*/
    
    r++;
    que[r] = u;
    dist[u] = 0;
    while (l<r)
    {
        long now = que[++l];
        used[now] = false;
        for (long i=f[now];i<m+1;i++)
        {
            if (bian[i].f!=now)    break;
            if (attract[bian[i].t]<=mid
                &&dist[bian[i].t]>dist[now]+bian[i].v)
            //不能加的边 
            {
                dist[bian[i].t]=dist[now]+bian[i].v;
                if (!used[bian[i].t])
                {
                    if (l==0||dist[que[l+1]]<=dist[bian[i].t])
                    {
                        used[bian[i].t] = true;
                        que[++r] = bian[i].t;
                    }
                    else
                    {
                        used[bian[i].t] = true;
                        que[l--] = bian[i].t;
                    }
                }
            }
        }
    }
    if (dist[v]<=t)
        return true;
    else
        return false;
}

int main()
{
    freopen("1609.in","r",stdin);
    freopen("1609.out","w",stdout);
    //scanf("%ld %ld %ld %ld %ld",&n,&m,&u,&v,&t);
    std::cin >> n >> m >> u >> v >> t;
    for (long i=1;i<n+1;i++)
    {
        //scanf("%ld",attract+i);
        std::cin >> attract[i];
        sum += attract[i];
    }
    for (long i=1;i<m+1;i++)
    {
        long x;long y;long long c;
        //scanf("%ld %ld %ld",&x,&y,&c);
        std::cin >> x >> y >> c;
        insert(x,y,c);
        insert(y,x,c);
    }
    m*=2;
    qsort(bian+1,m,sizeof(ftv),&bigger);
    for (long i=1;i<m+1;i++)
        if (f[bian[i].f]==0)
            f[bian[i].f]=i;
    long long l=0;long long r=sum;
    long long ans=oo;
    while (l<=r)
    {
        long long mid = (l+r)>>1;
        if (can(mid))
        {
            if (mid<ans)
                ans = mid;
            r = mid-1;
        }
        else
            l = mid+1;
    }
    if (ans < oo)
        std::cout << ans;
    else std::cout << -1;
} 






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值