ZOJ1027 Travelling Fee(DP+SPFA)
给一张有向无环图,边都有花费,从某点到某点走的那条路径上的那一条花费最多的边可以省掉,问从起点到终点的最少花费的多少,
往DP想的话,就可以写出这个状态dp[u][mx],表示到达u点已经省掉的花费为mx的最少花费。
用SPFA更新转移方程。。或者理解成队列+我为人人的转移。。其实这题这样子也能解有环图。
看了别人博客,发现还有三种解法:
- 枚举每一条边作为省掉的边,n次SPFA。这方法简洁,可惜想不出= =
- 跑Dijkstra,根据记录到每一点时的最长边更新,正确性不懂。。
- 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 }