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]
原文地址:https://www.cnblogs.com/jh818012/p/3182681.html