欢迎来到lbxer的博客
lbxer
lbxer
晓看天色暮看云,行也思君,坐也思君

csp赛前刷题篇 图论篇 UVA11367 Full Tank?

洛谷 UVA11367

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 }
View Code

 

可以考虑用堆来优化,每次一个点的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 }
View Code

当图稠密时,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 }
View Code

 

posted @ 2020-10-12 11:32  雷痕小祥  阅读(101)  评论(0编辑  收藏  举报
Live2D