zoukankan      html  css  js  c++  java
  • 2019 西安邀请赛 M

    Problem Description
    There are n planets in the MOT galaxy, and each planet has a unique number from 1∼n. Each planet is connected to other planets through some transmission channels. There are m transmission channels in the galaxy. Each transmission channel connects two different planets, and each transmission channel has a length.
    The residents of the galaxy complete the interplanetary voyage by spaceship. Each spaceship has a level. The spacecraft can be upgraded several times. It can only be upgraded 1 level each time, and the cost is c. Each upgrade will increase the transmission distance by d and the number of transmissions channels by e to the spacecraft. The spacecraft can only pass through channels that are shorter than or equal to its transmission distance. If the number of transmissions is exhausted, the spacecraft can no longer be used.
    Alice initially has a 0-level spacecraft with transmission distance of 0 and transmission number of 0. Alice wants to know how much it costs at least, in order to transfer from planet 1 to planet n.
    
    Input
    Each test file contains a single test case. In each test file:
    The first line contains n, m, indicating the number of plants and the number of transmission channels.
    The second line contains c, d, e, representing the cost, the increased transmission distance, and the increased number of transmissions channels of each upgrade, respectively.
    Next m lines, each line contains u,v,w, meaning that there is a transmission channel between u and v with a length of w.(2≤n≤105, n-1≤m≤105,1≤u,v≤n ,1≤c,d,e,w≤105)
    (The graph has no self-loop , no repeated edges , and is connected)
    
    Output
    Output a line for the minimum cost. Output -1 if she can’t reach.
    
    Sample Input
    5 7
    1 1 1
    1 2 1
    1 3 5
    1 4 1
    2 3 2
    2 4 5
    3 4 3
    3 5 5
    
    Sample Output
    5
    
    题意
    有n个点,编号从1到n,有m条边,每条边有一个长度w。
    Alice有一艘飞船,Alice可以给它升级很多次(无限),每升级一次需要花费c,升级一次之后飞船单次可飞行距离增加d,可飞行次数增加e。如果飞船需要飞过一条边,就需要满足单次可飞行距离≥这条路的长度同时可飞行次数不为0。
    现在Alice在编号为1的点,她的飞船为0级,单次可飞行距离和可飞行次数都为0,请你求出最小的花费使得Alice可以到达n点,如果不能到达n则输出-1
       // 二分更新次数
       //无环无向图且联通 ,就是树 
        #include <iostream>
        #include <cstdio>
        #include <queue>
        #include <cstring>
        using namespace std;
        #define ll long long 
        #define P pair<ll,ll>
        #define N 100100
        #define inf 1e12
        int n,m,cnt;
        ll c,d,E;ll u,v,w;
        ll head[N*2];
        ll dis[N],num[N];
        struct Node{
            ll u,v,w,nex;
            Node(){
            }
            Node(ll u,ll v,ll w,ll nex):u(u),v(v),w(w),nex(nex){}
        }e[N*2];
        void init()
        {
            cnt = 0;
            memset(head,-1,sizeof(head));
        }
        void add(ll u,ll v,ll w)
        {
            e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;
            e[cnt].nex = head[u];head[u]=cnt++;
        }
        bool check(ll mid)
        {
            //假设在起点就已经更新了mid次,验证mid是否满足条件 
            priority_queue<P,vector<P>,greater<P> >q;
            fill(dis,dis+n+1,inf);fill(num,num+n+1,inf);
            dis[1]=num[1]=0; 
            q.push(P(0,1));
            while(!q.empty())
            {
                P tmp =q.top();q.pop();
                ll u=tmp.second;
                if(dis[u]<tmp.first) continue;
                for(ll  i=head[u];i!=-1;i=e[i].nex){
                    ll v=e[i].v;
                    if(dis[v]>dis[u]+e[i].w&&e[i].w<=mid*d){
                        dis[v] = dis[u] +e[i].w;
                        num[v] = min(num[v],num[u]+1);//更新出最小的 
                        q.push(P(dis[v],v));
                    }
                }
            }
            return num[n]<=mid*E;//1: 可以走到n 2 :走过的路径数目满足条件 
        }
        int main()
        {
            init();
            scanf("%d%d",&n,&m);
            scanf("%lld%lld%lld",&c,&d,&E);
            for(int i =0;i<m;i++) {
                scanf("%lld%lld%lld",&u,&v,&w);
                add(u,v,w);add(v,u,w);
            }
            ll l =1,r=100000,res,mid;
            while(l<=r)
            {
                mid = (l+r)>>1;
                if(check(mid)) {    
                    res = mid;r=mid-1;
                }
                else{
                    l=mid+1;
                }
            }
            printf("%lld
    ",res*c);
            return 0;
        }
        //code2
           #include <iostream>
        #include <cstdio>
        #include <queue>
        #include <cstring>
        using namespace std;
        #define ll long long 
        #define P pair<ll,ll>
        #define N 100100
        #define inf 1e12
        int n,m,cnt;
        ll c,d,E;ll u,v,w;
        ll head[N*2];
        bool vis[N]; 
        struct Node{
            ll u,v,w,nex;
            Node(){
            }
            Node(ll u,ll v,ll w,ll nex):u(u),v(v),w(w),nex(nex){}
        }e[N*2];
        void init()
        {
            cnt = 0;
            memset(head,-1,sizeof(head));
        }
        void add(ll u,ll v,ll w)
        {
            e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;
            e[cnt].nex = head[u];head[u]=cnt++;
        }
        bool check(ll mid) 
        {
            /*
            由于是树,那么任意两点的路径唯一
            只需要判断在 当前的次数下,在满足单次可飞行距离≥这条路的长度下,凭借的当前可用步数能走到n吗 
            */ 
            memset(vis,0,sizeof(vis));//每次都是重新来 
            ll num =mid*E;ll dd = mid*d;
            //假设在起点就已经更新了mid次,验证mid是否满足条件 
            queue<P>q ;
            q.push(P(1,num)); //first :当前 到达的点 second :还余下的可走的步数 
            vis[1]=1;
            while(!q.empty())
            {
                P tmp =q.front();q.pop();
                ll u = tmp.first;ll cnt=tmp.second;
                if(u==n) return 1;
                else{
                    for(ll i=head[u];i!=-1;i=e[i].nex){
                        ll v=e[i].v;
                        if(!vis[v]&&e[i].w<=dd&&cnt>0){
                            vis[v] = 1;
                            q.push(P(v,cnt-1));
                        }
                    }
                }
            }
            return 0;
        }
        int main()
        {
            init();
            scanf("%d%d",&n,&m);
            scanf("%lld%lld%lld",&c,&d,&E);
            for(int i =0;i<m;i++) {
                scanf("%lld%lld%lld",&u,&v,&w);
                add(u,v,w);add(v,u,w);
            }
            ll l =1,r=100000,res,mid;
            while(l<=r)
            {
                mid = (l+r)>>1;
                if(check(mid)) {    
                    res = mid;r=mid-1;
                }
                else{
                    l=mid+1;
                }
            }
            printf("%lld
    ",res*c);
            return 0;
        }
  • 相关阅读:
    [dfs+水] hdu 4462 Scaring the Birds
    [Leetcode]-containsNearbyDuplicate
    測试流程的规范性与重要性
    柯里化函数之Javascript
    android AChartEngine源代码
    Android高斯模糊
    linux64位系统中g++4.4.7下使用wcsncpy函数有造成段错误的BUG(其它g++版本号未知)
    便利贴女孩_百度百科
    法爱格官方旗舰店
    法爱格2014 春夏新款欧美纯色修身高腰无袖吊带V领 拼接性感 连衣裙 黑色 M【图片 价格 品牌 报价】-京东
  • 原文地址:https://www.cnblogs.com/tingtin/p/11272615.html
Copyright © 2011-2022 走看看