zoukankan      html  css  js  c++  java
  • 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
    ",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
    ");
    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
  • 相关阅读:
    OOP & Pointer: Segment Tree
    ICPC_2020 上海站
    Notes: Kirchhoff's Matrix 基尔霍夫矩阵
    CS61A Homework: Church Numerals
    题解:[COCI2011-2012#5] BLOKOVI
    题解:SDOI2017 新生舞会
    题解:POI2012 Salaries
    题解:洛谷P1357 花园
    题解:CF593D Happy Tree Party
    题解 P2320 【[HNOI2006]鬼谷子的钱袋】
  • 原文地址:https://www.cnblogs.com/lbxer/p/13801740.html
Copyright © 2011-2022 走看看