csp赛前刷题篇 图论篇 UVA11367 Full Tank?
1思路 爆搜 但是会炸呀
2思路 优先队列搜索 (优先队列优化dijkstra)
DIJKSTRA
贪心策略,无法处理负权边,求单源最短路 维护两个点集:S集,T集。T集表示:源点到这个点的最短路(f值)不再改变,并已用这个点更新过这个点出边指向的其他点。
初始时所有点都在S集,每次取S集中最短路(f值),用f更新它所连的其他点。最后将这个点从S集删去,加入T集中。复杂度O(n^2)
代码如下:
1 for (int i = 1; i <= n; i++) 2 { 3 int t = 0; 4 for(int j=1;j<=n;j++) 5 if (!v[j]) { 6 if (!t || f[j] < f[t]) 7 t = j; 8 } 9 v[t] = 1; 10 for (int j = 1; j <= n; j++) { 11 f[j] = min(f[j], f[t] + a[t][j]); 12 //a为邻接矩阵 13 } 14 }
可以考虑用堆来优化,每次一个点的f值被更新,就把f加入一个堆中,如此每次从S堆中找一个min f。这样复杂度O(mlogm)。
代码如下:
1 priority_queue<pair<int, int>>que; 2 que.push(make_pair(f[S], S)); 3 while (!que.empty()) 4 { 5 pair<int, int>tmp = que.top(); 6 que.pop(); 7 int t = tmp.second; 8 if (vis[t])continue; 9 vis[t] = 1; 10 for(int i=head[t];i;i=nex[i]) 11 if (f[to[i]] > f[t] + val[i]) { 12 f[to[i]] > f[t] + val[i]; 13 que.push(make_pair(f[to[i]], to[i])); 14 } 15 }
当图稠密时,dijkstra不使用堆优化更高效。
回到本题,用一个小根堆维护当前位置和距离值。对于每一个问题,进行BFS
令初始状态(S,0)每一个状态有两个分支 1油够,前往下一个城市(next,oil-w)2.oil不够,加一升oil 状态(city,oil+1) 花费(price[city])
代码实现如下:
1 #include<iostream> 2 #include<algorithm> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdlib> 6 #include<ctime> 7 #include<cstdio> 8 using namespace std; 9 struct Heap{int city,oil,money;}D[100005]; 10 int S,T,C,V[1005][105],Map[1005][1005],N,M,Top,Num[1005]; 11 void AddHeap(int x,int y,int z)//入堆,小根堆 12 { 13 Top++;D[Top].money=x;D[Top].city=y;D[Top].oil=z; 14 int Now=Top; 15 while(Now>1&&D[Now].money<D[Now/2].money)swap(D[Now],D[Now/2]),Now/=2; 16 } 17 void Delete()//删除堆顶 18 { 19 D[1]=D[Top];Top--; 20 int Now=1,P; 21 while(Now*2<=Top) 22 { 23 if(Now*2==Top||D[Now*2].money<=D[Now*2+1].money)P=Now*2; 24 if(Top>=Now*2+1&&D[Now*2].money>D[Now*2+1].money)P=Now*2+1; 25 if(D[P].money<D[Now].money)swap(D[P],D[Now]),Now=P;else break; 26 } 27 } 28 void BFS()//宽搜 29 { 30 Top=0;AddHeap(0,S,0);//money,city,oil 31 while(Top) 32 { 33 int City=D[1].city,Money=D[1].money,Oil=D[1].oil; 34 Delete();//Delete Top 35 V[City][Oil]=1; 36 if(City==T){printf("%d\n",Money);return;} 37 if(Oil<C&&!V[City][Oil+1])AddHeap(Money+Num[City],City,Oil+1); 38 for(int i=0;i<N;i++)if(Map[City][i]&&Oil>=Map[City][i]&&!V[i][Oil-Map[City][i]])AddHeap(Money,i,Oil-Map[City][i]); 39 } 40 printf("impossible\n"); 41 } 42 int main() 43 { 44 while(~scanf("%d%d",&N,&M)) 45 { 46 for(int i=0;i<N;i++)scanf("%d",&Num[i]); 47 int x,y,z; 48 for(int i=1;i<=M;i++) 49 { 50 scanf("%d%d%d",&x,&y,&z); 51 Map[x][y]=z;Map[y][x]=z;//无向图 52 } 53 int Q;scanf("%d",&Q); 54 for(int i=1;i<=Q;i++) 55 { 56 scanf("%d%d%d",&C,&S,&T); 57 BFS(); 58 memset(V,0,sizeof(V)); 59 } 60 } 61 return 0; 62 }