• OUC_省赛备战赛_#5 _F题 poj3662


    http://poj.org/problem?id=3662
    题意:求一条从1到n 的路径,其中可以选择k条路免费,问该路径中出去k条之后最大的边长度是多少。
    比赛的时候想到了一个正确的算法:二分答案+DP判定,但是写挫了一个地方,二分写反了好几遍,最后也没过,回来把二分改了就过了,
    dp[i][j]表示到达i点经过了j条大于L的路得到的最小的最大值。特判了一下无解和0的情况
    还有就是直接dp求解也是可以的,直接把状态表示成dp[i][j]表示到达i点使用了j条免费的路的到的最小的最大值 
    code1,这个写的好挫,还是两个人各写了一部分
    [code lang="cpp"]
    bool spfa(int L )
    {
        memset(vv,0,sizeof(vv));
        memset(dp,-1,sizeof(dp));
        while(!q.empty()) q.pop();
        bool ffff;
        ffff = false;
        node u,tu;
        u.v = s;
        u.big = 0 ;
        vv[s][0] = 1;
        dp[s][0] = 0;
        q.push(u);
        while(!q.empty())
        {
            u = q.front();
            q.pop();
            if(u.v == n)
            {
                if(u.big == k )
                {
                    if(dp[n][k] != -1)
                    {
                        ans = min(ans, dp[n][k]);
                    }
                }
    
                if (u.big>=k)
                    ffff = true;
                vv[u.v][u.big] = 0;
                continue;
            }
            for(int i = head[u.v] ; i!= -1; i = edge[i].next)
            {
                int v = edge[i].v;
                int tmp ;
                if(edge[i].val <= L )
                    tmp = max(dp[u.v][u.big], edge[i].val);
                else
                    tmp = dp[u.v][u.big];
                if(edge[i].val > L)
                {
                    if((tmp < dp[v][u.big + 1] || dp[v][u.big + 1] == -1 )&&(u.big+1<=k))
                    {
                        dp[v][u.big + 1] = tmp;
                        if(!vv[v][u.big + 1])
                        {
                            tu.v = v;
                            tu.big = u.big + 1;
                            q.push(tu);
                            vv[v][u.big + 1]  = 1;
                        }
                    }
                }
                else
                {
                    if(tmp < dp[v][u.big] || dp[v][u.big] == -1)
                    {
                        dp[v][u.big] = tmp;
                        if(!vv[v][u.big])
                        {
                            tu.v = v;
                            tu.big = u.big;
                            q.push(tu);
                            vv[v][u.big] = 1;
                        }
                    }
                }
            }
            vv[u.v][u.big] = 0;
        }
        return ffff;
    }
    bool vis[maxn];
    int que[maxn];
    int dis[maxn];
    bool check()
    {
        memset(vis,false,sizeof(vis));
        memset(dis,-1,sizeof(dis));
        int hh = 0,tail = 1;
        que[1] = 1;
        vis[1] = 1;
        dis[1] = 0;
        while (hh < tail)
        {
            int u = que[++hh];
            for (int j= head[u];j!=-1;j=edge[j].next){
                int v = edge[j].v;
                if (dis[u]+1<dis[v] || dis[v] == -1)
                {
                    dis[v] = dis[u] + 1;
                    if (!vis[v]){
                        que[++tail] = v;
                        vis[v] = 1;
                    }
                }
            }
            vis[u] = 0;
        }
        if (dis[n]!=-1 && dis[n]<=k)
            return true;
        return false;
    }
    int main()
    {
        int u,v,val;
        while(scanf("%d%d%d",&n,&p,&k)!=EOF)
        {
            cnt = 0 ;
            s = 1;
            memset(head,-1,sizeof(head));
            int mmjh = 0;
            for(int i = 0 ; i < p ; i ++ )
            {
                scanf("%d%d%d",&u,&v,&val);
                addedge(u,v,val);
                mmjh = max(mmjh,val);
            }
            if (check())
            {
                printf("0\n");
                continue;
            }
            int left,right,mid;
            left = 1 ;
            right = mmjh;
            ans = inf;
            while(left < right )
            {
                mid = (left + right )/2;
                bool flag;
                flag = spfa(mid);
                if(flag == 0 )
                {
                    left = mid + 1 ;
                }
                else{
                    right = mid ;
                }
            }
            if (ans == inf)
            {
                ans = -1;
            }
            printf("%d\n",ans);
    
        }
        return 0;
    }
    [/code]
    
    
    code2
    [code lang="cpp"]
    void spfa()
    {
        memset(vv,0,sizeof(vv));
        for(int i = 0 ; i <= n; i ++ )
        {
            for(int j = 0; j <= k; j ++ )
            {
                dp[i][j] = inf;
            }
        }
        while(!q.empty()) q.pop();
        node u,tu;
        u.v = s;
        u.big = 0 ;
        vv[s][0] = 1;
        dp[s][0] = 0;
        q.push(u);
        while(!q.empty())
        {
            u = q.front();
            q.pop();
            if(u.v == n )
            {
                //printf("%d %d %d\n",u.v,u.big, dp[u.v][u.big]);
                ans = min(ans , dp[u.v][u.big]);
            }
            for(int i = head[u.v] ; i!= -1; i = edge[i].next)
            {
                int v = edge[i].v;
                int tmp ;
                tmp = max(dp[u.v][u.big] , edge[i].val);
                if(dp[v][u.big] > tmp )
                {
                    dp[v][u.big] = tmp;
                    if(!vv[v][u.big])
                    {
                        tu.v = v;
                        tu.big = u.big;
                        q.push(tu);
                        vv[v][u.big]  = 1;
                    }
                }
                if(u.big < k && dp[u.v][u.big] < dp[v][u.big + 1 ] )
                {
                    dp[v][u.big + 1] = dp[u.v][u.big];
                    if(!vv[v][u.big + 1])
                    {
                        tu.v = v;
                        tu.big = u.big + 1;
                        q.push(tu);
                        vv[v][u.big + 1] = 1;
                    }
                }
            }
            // printf("\n");
            vv[u.v][u.big] = 0;
        }
    }
    int main()
    {
        int u,v,val;
        while(scanf("%d%d%d",&n,&p,&k)!=EOF)
        {
            cnt = 0 ;
            s = 1;
            memset(head,-1,sizeof(head));
            for(int i = 0 ; i < p ; i ++ )
            {
                scanf("%d%d%d",&u,&v,&val);
                addedge(u,v,val);
            }
            ans = inf;
            spfa();
            if (ans == inf)
            {
                ans = -1;
            }
            printf("%d\n",ans);
    
        }
        return 0;
    }
    [/code]
  • 相关阅读:
    Python进阶06 循环对象
    Python进阶05 循环设计
    Python进阶 函数的参数对应
    Python进阶01 词典
    Python基础 反过头来看看
    Python基础08 面向对象的基本概念
    利用zepto.js实现移动页面图片全屏滑动
    数组弃重方法
    fcc筆記
    文字颜色渐变效果
  • 原文地址:https://www.cnblogs.com/jh818012/p/3182681.html
Copyright © 2020-2023  润新知