【勤劳的小熊】解题报告

来源:互联网 发布:mac显示隐藏照片 编辑:程序博客网 时间:2024/04/27 00:14

//tyvj1609

背景 BackgroundAndyBear 生日模拟赛 第三题描述 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;} 



原创粉丝点击