HDU 3873 Invade the Mars(带限制条件的Dijkstra)

Posted ventricle

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 3873 Invade the Mars(带限制条件的Dijkstra)相关的知识,希望对你有一定的参考价值。

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

思路:

军队可以先等待在城市外面,等保护该城市的城市都被攻破后,直接进城(即进城不用耗费时间)。则进入该城市的最少时间为max(达到该城市的最少时间,到达保护该城市的所有城市的最大时间)。

用num[i]标记第i个城市被保护的数目,只有当该点被保护的数目为0时,才能入S集合,从而优化到其他点的时间。当前进入S集合的城市,遍历它所保护的城市,num[i]减一,记录下被保护的城市解除保护所需的最长时间。

说的有点绕,看代码会比较清楚。

需要注意的一点!!有重边,所以读边的时候要注意,如果是用邻接表就无所谓啦,但如果是用邻接矩阵 要读入最小值。

 

代码:

 1 #include <cstdio>
 2 #include <vector>
 3 #include <cstring>
 4 #include <algorithm>
 5 using namespace std;
 6 const int inf=1e8+5;
 7 int n,m;
 8 int num[3005];
 9 int dist[3005];
10 int S[3005];
11 int edge[3005][3005];
12 int rp[3005];//rp[i]表示攻破保护i城市的所有城市所需要的最长时间
13 vector<int>city[3005];
14 void init(){
15     memset(num, 0, sizeof(num));
16     memset(rp, 0, sizeof(rp));
17     memset(S, 0, sizeof(S));
18     for (int i=1; i<=n; i++) {
19         city[i].clear();
20         dist[i]=inf;
21     }
22     for (int i=1; i<=n; i++) {
23         for (int j=1; j<=n; j++) {
24             edge[i][j]=inf;
25         }
26     }
27 }
28 void dijkstra(){
29     dist[1]=0;
30     for(int i=0;i<n;i++){
31         int Min=inf,u=-1;
32         for (int j=1; j<=n; j++) {
33             dist[j]=max(dist[j], rp[j]);//每次遍历前  都要更新时间
34             if(dist[j]<Min && !num[j] && !S[j]){
35                 Min=dist[j];
36                 u=j;
37             }
38         }
39         if(u==-1)   return ;
40         S[u]=1;
41         for (int j=0; j<city[u].size(); j++) {//更新保护的城市信息
42             int t=city[u][j];
43             num[t]--;
44             rp[t]=max(rp[t],dist[u]);
45         }
46         city[u].clear();
47         for (int j=1; j<=n; j++) {
48             if(dist[j]>dist[u]+edge[u][j] && !S[j]){
49                 dist[j]=dist[u]+edge[u][j];
50             }
51         }
52     }
53 }
54 int main(){
55     int t;
56     scanf("%d",&t);
57     while (t--) {
58         scanf("%d%d",&n,&m);
59         init();
60         for(int i=0;i<m;i++){
61             int v,u,w;
62             scanf("%d%d%d",&v,&u,&w);
63             edge[v][u]=min(edge[v][u],w);//保留最小值
64             
65         }
66         for(int i=1;i<=n;i++){
67             int a,b;
68             scanf("%d",&a);
69             num[i]=a;//记录保护i城市的所有城市数量
70             for (int j=0; j<a; j++) {
71                 scanf("%d",&b);
72                 city[b].push_back(i);//city[b]为b城市 要保护的城市
73             }
74         }
75         dijkstra();
76         printf("%d\n",dist[n]);
77     }
78     return 0;
79 }

 

以上是关于HDU 3873 Invade the Mars(带限制条件的Dijkstra)的主要内容,如果未能解决你的问题,请参考以下文章

hdu1800 Flying to the Mars(字典树)

HDU1800Flying to the Mars(字典树)

hdu_2124 Flying to the Mars & hdu_1800 Repair the Wall 贪心水题

HDU 1800——Flying to the Mars——————字符串哈希

Flying to the Mars HDU - 1800(字典树)

HDU 4059:The Boss on Mars(数学公式+容斥原理)