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;
        }
  • 相关阅读:
    【新提醒】N820 N821 android 4.2 V1.1版
    Silk Icons —— 再来 700 个免费小图标
    解决基于BAE python+bottle开发上的一系列问题
    gae 已死,别整什么反向代理了,用sae吧,还有在线编辑工具
    MDCC为移动开发者服务:一看、一聊、一聚
    Testin_百度百科
    我们的开源项目-暨开源力量公开课年度庆典活动
    Kivy: Crossplatform Framework for NUI
    进京通行证_百度百科
    史丹·温斯坦称傲牛熊市的秘密_百度百科
  • 原文地址:https://www.cnblogs.com/tingtin/p/11272615.html
Copyright © 2011-2022 走看看