ZOJ1027 Travelling Fee(DP+SPFA)

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

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

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

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

  1. 枚举每一条边作为省掉的边,n次SPFA。这方法简洁,可惜想不出= =
  2. 跑Dijkstra,根据记录到每一点时的最长边更新,正确性不懂。。
  3. Floyd+DP:加个维度,dpk[0\1][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\n",res);
72     }
73     return 0;
74 }

 

posted @ 2016-02-27 17:00  WABoss  阅读(235)  评论(0编辑  收藏  举报