• ZOJ1027 Travelling Fee(DP+SPFA)


    给一张有向无环图,边都有花费,从某点到某点走的那条路径上的那一条花费最多的边可以省掉,问从起点到终点的最少花费的多少,

    往DP想的话,就可以写出这个状态dp[u][mx],表示到达u点已经省掉的花费为mx的最少花费。

    用SPFA更新转移方程。。或者理解成队列+我为人人的转移。。其实这题这样子也能解有环图。

    看了别人博客,发现还有三种解法:

    1. 枚举每一条边作为省掉的边,n次SPFA。这方法简洁,可惜想不出= =
    2. 跑Dijkstra,根据记录到每一点时的最长边更新,正确性不懂。。
    3. Floyd+DP:加个维度,dpk[01][u][v],第一维1和0分别表示省和没省最长边的最少花费,dp[1]的转移就是dp[1][u][v]=min(dp[0][u][k]+dp[1][k][v],dp[1][u][k]+dp[0][k][v]),初始dp[1][i][j]=0(<i,j>∈E),好厉害。。
     1 #include<cstdio>
     2 #include<cstring>
     3 #include<iostream>
     4 #include<queue>
     5 #include<string>
     6 #include<algorithm>
     7 using namespace std;
     8 #define INF (1<<29)
     9 int n,G[222][222];
    10 int d[222][10001];
    11 bool vis[222][10001];
    12 struct Node{
    13     int u,mx;
    14     Node(int _u,int _mx):u(_u),mx(_mx){}
    15 };
    16 void SPFA(int vs){
    17     for(int i=0; i<n; ++i){
    18         for(int j=0; j<10001; ++j) d[i][j]=INF;
    19     }
    20     d[vs][0]=0;
    21     memset(vis,0,sizeof(vis));
    22     vis[vs][0]=1;
    23     queue<Node> que;
    24     que.push(Node(vs,0));
    25     while(!que.empty()){
    26         Node nd=que.front(); que.pop();
    27         int u=nd.u,mx=nd.mx;
    28         for(int v=0; v<n; ++v){
    29             if(G[u][v]==INF) continue;
    30             if(G[u][v]>mx && d[v][G[u][v]]>d[u][mx]+mx){
    31                 d[v][G[u][v]]=d[u][mx]+mx;
    32                 if(!vis[v][G[u][v]]){
    33                     vis[v][G[u][v]]=1;
    34                     que.push(Node(v,G[u][v]));
    35                 }
    36             }
    37             if(d[v][mx]>d[u][mx]+G[u][v]){
    38                 d[v][mx]=d[u][mx]+G[u][v];
    39                 if(!vis[v][mx]){
    40                     vis[v][mx]=1;
    41                     que.push(Node(v,mx));
    42                 }
    43             }
    44         }
    45         vis[u][mx]=0;
    46     }
    47 }
    48 int main(){
    49     string name[222],x[111],y[111],vs,vt;
    50     int m,z[111];
    51     while(cin>>vs>>vt){
    52         n=0;
    53         scanf("%d",&m);
    54         for(int i=0; i<m; ++i){
    55             cin>>x[i]>>y[i]>>z[i];
    56             name[n++]=x[i]; name[n++]=y[i];
    57         }
    58         sort(name,name+n);
    59         n=unique(name,name+n)-name;
    60         for(int i=0; i<n; ++i){
    61             for(int j=0; j<n; ++j) G[i][j]=INF;
    62         }
    63         for(int i=0; i<m; ++i){
    64             int u=lower_bound(name,name+n,x[i])-name,v=lower_bound(name,name+n,y[i])-name;
    65             G[u][v]=z[i];
    66         }
    67         SPFA(lower_bound(name,name+n,vs)-name);
    68         int tv=lower_bound(name,name+n,vt)-name;
    69         int res=INF;
    70         for(int i=0; i<10001; ++i) res=min(res,d[tv][i]);
    71         printf("%d
    ",res);
    72     }
    73     return 0;
    74 }
  • 相关阅读:
    《Linux shell变量总结回顾》RHEL6(转)
    20个最受欢迎的Linux命令(转)
    如果看了这篇文章你还不懂傅里叶变换,那就过来掐死我吧(转)
    妻共贫贱难,夫共富贵难
    [置顶] 阅读Oracle官方文档指南
    Java实现 蓝桥杯 算法训练 递归求二项式系数
    Java实现 蓝桥杯 算法训练 数字三角形
    Java实现 蓝桥杯 算法训练 数字三角形
    Java实现 蓝桥杯 算法训练 数字三角形
    Java实现 蓝桥杯 算法训练 数字三角形
  • 原文地址:https://www.cnblogs.com/WABoss/p/5223179.html
Copyright © 2020-2023  润新知