P1084 疫情控制

来源:互联网 发布:网络综艺节目不好 编辑:程序博客网 时间:2024/05/02 02:16

题目描述

H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都,

也是树中的根节点。

H 国的首都爆发了一种危害性极高的传染病。当局为了控制疫情,不让疫情扩散到边境

城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境

城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点。但特别要注意的是,

首都是不能建立检查点的。

现在,在 H 国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队。一支军队可以在有道路连接的城市间移动,并在除首都以外的任意一个城市建立检查点,且只能在

一个城市建立检查点。一支军队经过一条道路从一个城市移动到另一个城市所需要的时间等

于道路的长度(单位:小时)。

请问最少需要多少个小时才能控制疫情。注意:不同的军队可以同时移动。

输入输出格式

输入格式:

第一行一个整数 n,表示城市个数。

接下来的 n-1 行,每行 3 个整数,u、v、w,每两个整数之间用一个空格隔开,表示从

城市 u 到城市 v 有一条长为 w 的道路。数据保证输入的是一棵树,且根节点编号为 1。

接下来一行一个整数 m,表示军队个数。

接下来一行 m 个整数,每两个整数之间用一个空格隔开,分别表示这 m 个军队所驻扎

的城市的编号。

输出格式:

共一行,包含一个整数,表示控制疫情所需要的最少时间。如果无法控制疫情则输出-1。


先二分个答案吧--

显然,在有限时间内,每个军队不断往上走总是比往下走更优的,因为这样能控制的范围更大

问题在于,有些子树可能根本不存在军队,,这就使得必须从某个军队很多的子树中抽调部分军队来填补空缺

而这样走的最优方案,是某个选定军队先走到根然后往那个缺少军队的子树走一步,就是直接走到这个子树,这样一定是最优的

来模拟这个过程,,首先找出每个军队最多能往上走到哪里,这个倍增算法解决

剩下的地方就是贪心了

一个军队最多为一棵子树建立检查点

在二分出的时限内,有些军队能到达根,有些不能,,对于不能的,就直接检查他们是否能够为自己所在的那个子树完成防疫任务

对于可以的,,,按照他们到达根以后剩下的时间从小到大排序

对于所有子树,按照根到它们的距离从小到大排序

剩余时间少的军队能解决的子树,这个子树到根的距离越大,那么这种匹配就更优

从小到大枚举子树,同时枚举军队

对于一个军队,他要么解决连续的几个到根距离少于时限的子树的其中之一,要么解决他出发点的子树

如果出发点子树还没循环到,而且它还没被处理,,显然先分配给他最优

如上贪心即可



写的时候没一起更新Mark数组,,,GG了

#include<iostream>  #include<cstdio>  #include<cstring>  #include<algorithm>  #include<cmath>  #include<vector>  using namespace std;    const int maxn = 5E4 + 50;  const int INF = ~0U>>1;  typedef long long LL;    struct E{      int to,w;      E(){}      E(int to,int w): to(to),w(w){}  };    struct data{      int num; LL rest;      data(){}      data(int num,LL rest): num(num),rest(rest){}      bool operator < (const data &b) const {return rest < b.rest;}  }f[maxn];    int n,m,cnt,Mark[maxn],L[maxn],fa[maxn][20],pos,ti      ,Army[maxn],City[maxn],Belong[maxn],Be,son;  LL w[maxn][20];    vector <E> v[maxn];  vector <int> Arm[maxn];    void Pre_Work(int x){    for (int i = 0; i < Arm[x].size(); i++)           Belong[Arm[x][i]] = Be;      for (int i = 1; i < 20; i++) {          fa[x][i] = fa[fa[x][i-1]][i-1];          w[x][i] = w[fa[x][i-1]][i-1] + w[x][i-1];      }  }  void Dfs(int x,int from)  {      if (L[x] == 2) Be = x;      Pre_Work(x);    for (int i = 0; i < v[x].size(); i++) {          int to = v[x][i].to;          if (to == from) continue;          int z = v[x][i].w;          w[to][0] = z;          fa[to][0] = x;          L[to] = L[x] + 1;          Dfs(to,x);      }  }    void Work(int x,LL now)  {      ti = 0; int y = 1<<19;      for (int j = 19; j >= 0; j--,y >>= 1) {          if (L[x] - y < 1) continue;          if (ti + w[x][j] > now) continue;          ti += w[x][j];          x = fa[x][j];      }      pos = x;      if (pos != 1) ti = INF;  }    bool Dfs2(int x,int from)  {      if (Mark[x] == cnt) return 1;      if (v[x].size() == 1) return 0;      for (int i = 0; i < v[x].size(); i++) {          int to = v[x][i].to;          if (to == from) continue;          if (!Dfs2(to,x)) return 0;      }      return 1;  }    bool Judge(LL now)  {      int tot = 0; ++cnt;      for (int i = 1; i <= m; i++) {          Work(Army[i],now);          if (ti <= now) f[++tot] = data(Belong[i],now - ti);          else Mark[pos] = cnt;      }      sort(f + 1,f + tot + 1);      for (int i = 0; i < v[1].size(); i++) {          int to = v[1][i].to;          if (Mark[to] == cnt) continue;          if (Dfs2(to,1)) Mark[to] = cnt;      }            int t = 1;      for (int i = 1; i <= son; i++) {          int k = City[i];          if (Mark[k] == cnt) continue;          bool flag = 0;          for (; t <= tot; ++t) {              if (Mark[f[t].num] != cnt) {                  Mark[f[t].num] = cnt;                  if (f[t].num == k) {flag = 1; ++t; break;}                  continue;              }              if (f[t].rest < w[k][0]) continue;              flag = 1;              Mark[k] = cnt;            ++t; break;          }          if (!flag) return 0;      }      return 1;  }    int getint()  {      char ch = getchar();      int ret = 0;      while (ch < '0' || '9' < ch) ch = getchar();      while ('0' <= ch && ch <= '9')          ret = ret*10 + ch - '0',ch = getchar();      return ret;  }    bool cmp(const int &a,const int &b) {return w[a][0] < w[b][0];}    int main()  {      #ifdef DMC          freopen("DMC.txt","r",stdin);      #endif            n = getint();      LL R = 0;      for (int i = 1; i < n; i++) {          int x,y,w;          x = getint();          y = getint();          w = getint();          v[x].push_back(E(y,w));          v[y].push_back(E(x,w));          R += w;      }  m = getint();      for (int i = 1; i <= m; i++) {Army[i] = getint();Arm[Army[i]].push_back(i);      }    L[1] = 1; Dfs(1,0);      son = v[1].size();      for (int i = 0; i < son; i++) City[i+1] = v[1][i].to;      sort(City + 1,City + son + 1,cmp);          LL L = 0;      while (R - L > 1) {          LL mid = (L + R) >> 1LL;          if (Judge(mid)) R = mid;          else L = mid;      }      if (Judge(L)) cout << L;      else if (Judge(R)) cout << R;      else cout << -1;      return 0;  }  

0 0
原创粉丝点击