• 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;
        }
  • 相关阅读:
    eas之动态刷新Table
    eas之导入导出
    eas之事件
    eas之获得任何一个KDTable的选中行
    eas之创建一个UI界面并对其操作
    eas之style接口
    eas之指定虚模式
    eas之数据融合
    eas之kdtable格式化
    eas之视图冻结与解冻
  • 原文地址:https://www.cnblogs.com/tingtin/p/11272615.html
Copyright © 2020-2023  润新知