P1084 疫情控制
题目描述
H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,也是树中的根节点。
H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从 首都到边境城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,首都是不能建立检查点的。
现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在 一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等于道路的长度(单位:小时)。
请问最少需要多少个小时才能控制疫情。注意:不同的军队可以同时移动。
输入输出格式
输入格式:第一行一个整数 n,表示城市个数。
接下来的 n-1 行,每行 3 个整数,u、v、w,每两个整数之间用一个空格隔开,表示从城市 u 到城市 v 有一条长为 w 的道路。数据保证输入的是一棵树,且根节点编号为 1。
接下来一行一个整数 m,表示军队个数。
接下来一行 m 个整数,每两个整数之间用一个空格隔开,分别表示这 m 个军队所驻扎的城市的编号。
输出格式:共一行,包含一个整数,表示控制疫情所需要的最少时间。如果无法控制疫情则输出-1。
输入输出样例
4 1 2 1 1 3 2 3 4 3 2 2 2
3
说明
【输入输出样例说明】
第一支军队在 2 号点设立检查点,第二支军队从 2 号点移动到 3 号点设立检查点,所需时间为 3 个小时。
【数据范围】
保证军队不会驻扎在首都。
对于 20%的数据,2≤ n≤ 10;
对于 40%的数据,2 ≤n≤50,0<w <10^5;
对于 60%的数据,2 ≤ n≤1000,0<w <10^6;
对于 80%的数据,2 ≤ n≤10,000;
对于 100%的数据,2≤m≤n≤50,000,0<w <10^9。
NOIP 2012 提高组 第二天 第三题
【题解】
倍增写反了调了半天。。
各种细节
淦
写一下能想到的几点;
1、倍增写反了 淦
2、往根节点跳,跳不到就留下。跳上去回不来,如果那个点没有留下的,就留下;如果有留下的,就比较
剩余值的大小,小的留下。为什么回不去,且那个点没有留下的,就要留下?因为这个点回不去,一定需要
其他点填补,其他点剩余值比这个点大,不如让其他点做更大的事情
代码比较乱
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <algorithm> 6 7 const long long MAXN = 50000 + 10; 8 const long long MAXM = 50000 + 10; 9 10 inline void read(long long &x) 11 { 12 x = 0;char ch = getchar(), c = ch; 13 while(ch < '0' || ch > '9')c = ch, ch = getchar(); 14 while(ch <= '9' && ch >= '0')x = x * 10 + ch - '0', ch = getchar(); 15 if(c == '-')x = -x; 16 } 17 18 struct Edge 19 { 20 long long u,v,next,w; 21 Edge(long long _u, long long _v, long long _w, long long _next){u = _u;v = _v;w = _w;next = _next;} 22 Edge(){} 23 }edge[MAXN << 1]; 24 long long head[MAXN], cnt; 25 26 inline void insert(long long a, long long b, long long c) 27 { 28 edge[++cnt] = Edge(a, b, c, head[a]); 29 head[a] = cnt; 30 } 31 32 long long rank[MAXN],n,m,l,r,mid,fa[MAXN],have[MAXN],ans,have2[MAXN]; 33 34 long long b[MAXN],p[20][MAXN],len[20][MAXN],deep[MAXN]; 35 36 void dfs(long long u) 37 { 38 b[u] = 1; 39 for(register long long pos = head[u];pos;pos = edge[pos].next) 40 { 41 long long v = edge[pos].v; 42 if(b[v]) continue; 43 fa[v] = u; 44 deep[v] = deep[u] + 1; 45 p[0][v] = u, len[0][v] = edge[pos].w; 46 dfs(v); 47 } 48 } 49 long long M = 0; 50 51 void yuchuli() 52 { 53 while((1 << M) <= n) ++ M; 54 -- M; 55 56 for(register long long j = 1;j <= M;++ j) 57 for(register long long i = 1;i <= n;++ i) 58 p[j][i] = p[j - 1][p[j - 1][i]]; 59 for(register long long j = 1;j <= M;++j) 60 for(register long long i = 1;i <= n;++ i) 61 len[j][i] = len[j - 1][i] + len[j - 1][p[j - 1][i]]; 62 } 63 64 long long dfs2(long long u) 65 { 66 if(have2[u])return 1; 67 long long flag = 0; 68 for(register long long pos = head[u];pos;pos = edge[pos].next) 69 { 70 long long v = edge[pos].v; 71 if(fa[u] == v)continue; 72 flag = dfs2(v); 73 if(!flag)return 0; 74 } 75 return flag; 76 } 77 78 long long node1[MAXN], tot; 79 80 long long tot2, mi[MAXN]; 81 82 struct TT 83 { 84 int re, rank; 85 TT(int _re, int _rank){re = _re;rank = _rank;} 86 TT(){} 87 }tt[MAXN]; 88 89 bool cmpp(TT a, TT b) 90 { 91 return a.re < b.re; 92 } 93 94 long long check(long long ma) 95 { 96 memset(tt, 0, sizeof(tt)); 97 memset(have2, 0, sizeof(have2)); 98 memset(mi, 0, sizeof(mi)); 99 tot2 = 0; 100 101 for(register long long i = 1;i <= m;++ i) 102 { 103 long long now = rank[i], s = 0; 104 if(now == 1) 105 { 106 tt[++tot2].re = ma; 107 tt[tot2].rank = now; 108 continue; 109 } 110 for(register long long j = M;j >= 0;-- j) 111 if(s + len[j][now] <= ma && p[j][now] > 1) 112 s += len[j][now], now = p[j][now]; 113 if(fa[now] == 1 && ma - s - len[0][now] > 0) 114 { 115 if(ma - s - len[0][now] < len[0][now]) 116 { 117 if(!mi[now]) mi[now] = ma - s - len[0][now], have2[now] = 1; 118 else if(mi[now] > ma - s - len[0][now])tt[++tot2].re = mi[now], mi[now] = ma - s - len[0][now], tt[tot2].rank = now; 119 else tt[++tot2].re = ma - s - len[0][now], tt[tot2].rank = now; 120 } 121 else tt[++tot2].re = ma - s - len[0][now], tt[tot2].rank = now; 122 } 123 else ++ have2[now], mi[now] = ma - s - len[0][now]; 124 } 125 for(register int i = 2;i <= n;++ i) 126 { 127 int tmp = have2[i]; 128 -- have2[i]; 129 if(fa[i] == 1 && dfs2(i) && mi[i] > 0) 130 { 131 tt[++tot2].re = mi[i]; tt[tot2].rank = i; 132 -- tmp; 133 } 134 have2[i] = tmp; 135 } 136 std::sort(tt + 1, tt + 1 + tot2, cmpp); 137 long long now = 1; 138 for(register long long i = 1;i <= tot;++ i) 139 { 140 if(!dfs2(node1[i])) 141 { 142 if(now > tot2)return 0; 143 while(tt[now].re < len[0][node1[i]] && now <= tot2)++ now; 144 if(now > tot2)return 0; 145 ++ now; 146 } 147 } 148 return 1; 149 } 150 151 bool cmp(long long a, long long b) 152 { 153 return len[0][a] < len[0][b]; 154 } 155 156 int main() 157 { 158 read(n); 159 register long long tmp1, tmp2, tmp3; 160 for(register long long i = 1;i < n;++i) 161 { 162 read(tmp1), read(tmp2), read(tmp3); 163 insert(tmp1, tmp2, tmp3); 164 insert(tmp2, tmp1, tmp3); 165 r += tmp3; 166 } 167 read(m); 168 for(register long long j = 1;j <= m;++j) 169 read(rank[j]), have[rank[j]] = 1; 170 deep[1] = 1; 171 dfs(1); 172 for(register long long pos = head[1];pos;pos = edge[pos].next) 173 { 174 long long v = edge[pos].v; 175 if(v != 1) node1[++tot] = v; 176 } 177 yuchuli(); 178 std::sort(node1 + 1, node1 + 1 + tot, cmp); 179 l = 1; 180 while(l <= r) 181 { 182 mid = (l + r) >> 1; 183 if(check(mid)) ans = mid, r = mid - 1; 184 else l = mid + 1; 185 } 186 if(!ans) 187 { 188 printf("-1"); 189 return 0; 190 } 191 if(check(0))ans = 0; 192 printf("%lld", ans); 193 return 0; 194 }