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 }
时间: 2024-11-24 16:57:51

HDU 3873 Invade the Mars(带限制条件的Dijkstra)的相关文章

POJ 1062 昂贵的聘礼(带限制条件的dijkstra)

题目网址:http://poj.org/problem?id=1062 题目: 昂贵的聘礼 Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 49916   Accepted: 14961 Description 年轻的探险家来到了一个印第安部落里.在那里他和酋长的女儿相爱了,于是便向酋长去求亲.酋长要他用10000个金币作为聘礼才答应把女儿嫁给他.探险家拿不出这么多金币,便请求酋长降低要求.酋长说:"嗯,如果你能够替我弄到

HDU 2842 Chinese Rings (带常数矩阵+矩阵快速幂)

HDU 2842 Chinese Rings (带常数矩阵+矩阵快速幂) ACM 题目地址:HDU 2842 Chinese Rings 题意: 一种中国环,解开第k个环需要先解开前(k-2)个环,并留有第(k-1)环.问解开n环最少需要几步. 分析: 设f(n)表示解开n环. 1. 由于游戏规则,解开n环不能一下子把n-1全解开了,否则第n个就没法拿掉了. 2. 得先拿掉第n个:先完成f(n-2),然后再拿掉第n环. 3. 然后放回前(n-2),其实这也是f(n-2),因为是一个逆的过程. 4

hdu 3790 最短路径问题(两个限制条件的最短路)

http://acm.hdu.edu.cn/showproblem.php?pid=3790 有两个条件:距离和花费.首先要求距离最短,距离相等的条件下花费最小. dijkstra,只是在判断条件时多考虑了花费. 注意重边. #include <stdio.h> #include <algorithm> #include <set> #include <map> #include <vector> #include <math.h>

HDU 2544:最短路( 最短路径入门 &amp;&amp;Dijkstra &amp;&amp; floyd )

最短路 Time Limit: 5000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 30972    Accepted Submission(s): 13345 Problem Description 在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt.但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找

HDU 2066-一个人的旅行(最短路Dijkstra)

一个人的旅行 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 19349    Accepted Submission(s): 6763 Problem Description 虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰

hdu 3790 最短路径问题(双重权值,dijkstra算法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3790 题目大意:题意明了,输出最短路径及其花费. 需要注意的几点:(1)当最短路径相同时,输出最小花费!!! (2)更新路径的时候要注意更新花费. 1 #include <iostream> 2 #include <cstdio> 3 using namespace std; 4 const int INF=9999999; 5 int map[1010][1010],Min,n,co

HDU - 1728 逃离迷宫(带转弯的dfs)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1728 题意:从迷宫的一个点走到另一个点,要求转弯数不能超过k次,并且有可能走不到 典型的走迷宫问题,主要是如何处理转弯和剪枝的问题.转弯的话可以用if(dir!=-1&&i!=dir)来判断. 剪枝:1.找到,返回. 2.超出给定的转弯数,返回 3.刚好到给定的转弯数,但是没到指定要到的点,返回 4.超出给定的地图或碰到障碍物,换个方向走 5.可以从其他路径以更少的转弯次数到达,舍去现在路径,

hdu 3074 Zjnu Stadium (带权并查集)

Zjnu Stadium Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1744    Accepted Submission(s): 660 Problem Description In 12th Zhejiang College Students Games 2007, there was a new stadium built i

HDU(1856),裸的带权并查集

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1856 题意:朋友圈问题,A和B是朋友,B和C是朋友则A和C也是朋友,依次类推,题目的意思就是求最大的朋友圈,即求最大集合中元素的个数.裸的并查集加个秩数组就行了. #include <stdio.h> int father[100050]; int rank[100050]; int Find_Set (int x) { if(x!=father[x]) father[x] = Find_Set(