【HDU3873 Invade the Mars】有保护节点的最短路(优先队列+spfa)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3873

题目大意:美国佬打算入侵火星,火星上有n个城市,有些城市可能受其他城市保护,如果i城市受j城市保护,那么你必须先攻占j城市才能再攻占i城市,问你攻占城市n的最短时间是多少。

解题思路:开一个优先队列,每次将图中不受保护并的节点加入队列(注意不受保护的节点可能重复入队,所以要做个标记,只处理优先队列中第一个出来的重复节点),spfa()单源最短路进行操作,num[u]表示保护节点u的城市有多少个,当num[u]为0的时候可以把u加入队列。处理受保护的节点v时,disv=max(disu,dis[v]),disu表示达到保护u的最后一个节点的时间,dis[v]表示spfa到达v的最短时间,两者取最大值。

View Code
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <vector>
  5 #include <queue>
  6 #include <algorithm>
  7 using namespace std;
  8 
  9 const int maxn=3333;
 10 const long long oo=1000000007ll;
 11 typedef long long lld;
 12 int visit[maxn], num[maxn];
 13 lld  dis[maxn];
 14 int n;
 15 
 16 struct node
 17 {
 18     int x;
 19     lld dis;
 20     friend bool operator<(const node &A, const node &B)
 21     {
 22         return A.dis>B.dis;
 23     }
 24 };
 25 
 26 struct Node
 27 {
 28     int v, val;
 29     Node() {}
 30     Node(int v_, int val_)
 31     {
 32         v=v_, val=val_;
 33     }
 34 };
 35 vector<Node>vt[maxn];
 36 vector<int>ct[maxn];
 37 
 38 void spfa()
 39 {
 40     for(int i=1; i<=n; i++) dis[i]=oo, visit[i]=0;
 41     priority_queue<node>q;
 42     node s;
 43     s.x=1, s.dis=0;
 44     dis[s.x]=0;
 45     q.push(s);
 46     while(!q.empty())
 47     {
 48         int u=q.top().x;
 49         lld du=q.top().dis;
 50         q.pop();
 51         if(visit[u]) continue;  ///访问过的节点就不必在处理了
 52         visit[u]=1;
 53         if(u==n)
 54         {
 55             cout << du <<endl;
 56             return ;
 57         }
 58         for(int i=0; i<vt[u].size(); i++)
 59         {
 60             s.x=vt[u][i].v, s.dis=du+vt[u][i].val;
 61             if(s.dis<dis[s.x])
 62             {
 63                 dis[s.x]=s.dis;
 64                 if(!num[s.x])   q.push(s);
 65             }
 66         }
 67         for(int i=0; i<ct[u].size(); i++)
 68         {
 69             s.x=ct[u][i];
 70             if(visit[s.x]) continue;
 71             num[s.x]--;
 72             if(!num[s.x])
 73             {
 74                 s.dis=max(du,dis[s.x]);
 75                 q.push(s);
 76             }
 77         }
 78     }
 79 }
 80 
 81 int main()
 82 {
 83     int m, T;
 84     cin >> T;
 85     while(T--)
 86     {
 87         scanf("%d%d",&n,&m);
 88         for(int i=1; i<=n; i++) vt[i].clear(), ct[i].clear(), num[i]=0;
 89         for(int i=0; i<m; i++)
 90         {
 91             int u, v, val;
 92             scanf("%d%d%d",&u,&v,&val);
 93             vt[u].push_back(Node(v,val));
 94         }
 95         for(int i=1; i<=n; i++)
 96         {
 97             int x;
 98             scanf("%d",&num[i]);
 99             for(int j=1; j<=num[i]; j++)
100             {
101                 scanf("%d",&x);
102                 ct[x].push_back(i);
103             }
104         }
105         spfa();
106     }
107     return 0;
108 }
原文地址:https://www.cnblogs.com/kane0526/p/3056536.html