codevs 1218

只想到二分答案,每次先用倍增将点推上去。。。

推到根节点后就贪心,不能再走回去且这个点需要军队而且这个点剩余的时间是从这个节点推上来的节点中最小的就走回去(语文实在LJ。。。)

实现起来貌似很难但代码不是很长

第二次用到set了,做得比较慢。。。不学C艹真的会死得很惨。。。

WA一个点不造是怎么回事。。

  1 #include<bits/stdc++.h>
  2 #define inc(i,l,r) for(i=l;i<=r;i++)
  3 #define dec(i,l,r) for(i=l;i>=r;i--)
  4 #define mem(a) memset(a,0,sizeof(a))
  5 #define inf 1e9
  6 #define ll long long
  7 #define succ(x) (1<<x)
  8 #define NM 80000+5
  9 using namespace std;
 10 int read(){
 11     int x=0,f=1;char ch=getchar();
 12     while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
 13     while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
 14     return x*f;
 15 }
 16 struct edge{
 17     int t;
 18     ll v;
 19     edge *next;
 20 }e[2*NM],*h[NM];
 21 int f[NM][30],p=25,i,k,n,m,_x,_y,s,ff[NM],minn[NM];
 22 ll l,r,_t,b[NM],c[NM],d[NM][30],a[NM];
 23 bool v[NM],leaf[NM];
 24 multiset<ll>S;
 25 multiset<ll>::iterator it;
 26 void add(int x,int y,ll v){
 27     e[++s].t=y;e[s].v=v;e[s].next=h[x];h[x]=e+s;
 28 }
 29 void dfs(int x){
 30     v[x]++;
 31     inc(i,1,p){
 32         f[x][i]=f[f[x][i-1]][i-1];
 33         d[x][i]=d[f[x][i-1]][i-1]+d[x][i-1];
 34     }
 35     for(edge *j=h[x];j;j=j->next)
 36     if(!v[j->t]){
 37         leaf[x]=true;
 38         f[j->t][0]=x;
 39         d[j->t][0]=j->v;
 40         if(x==1){
 41         ff[j->t]=j->t;
 42         c[j->t]=j->v;
 43         }else ff[j->t]=ff[x];
 44         dfs(j->t);
 45     }
 46 }
 47 bool _dfs(int x,int k){
 48     if(!leaf[x]&&!v[x])return false;
 49     for(edge *j=h[x];j;j=j->next)
 50     if(j->t!=k&&!v[j->t])
 51     if(!_dfs(j->t,x))return false;
 52     return true;
 53 }
 54 bool check(){
 55     mem(v);mem(minn);mem(b);
 56     int num=0,tot=0;
 57     inc(i,1,m){
 58         ll t=_t,tmp=a[i];
 59         dec(k,p,0)
 60         if(t>=d[tmp][k]){
 61             t-=d[tmp][k];
 62             tmp=f[tmp][k];
 63         }
 64         if(tmp<=1){
 65             b[++tot]=t;
 66             if(t<=c[ff[a[i]]]&&(!minn[ff[a[i]]]||t<b[minn[ff[a[i]]]]))
 67             minn[ff[a[i]]]=tot;
 68         }else v[tmp]++;
 69     }
 70     for(edge *j=h[1];j;j=j->next)
 71     if(!v[j->t])v[j->t]=_dfs(j->t,1);
 72     inc(i,1,n)
 73     if(!v[i]&&minn[i])
 74     b[minn[i]]=0,v[i]++;
 75     sort(b+1,b+1+tot);
 76     S.clear();
 77 //    S.insert(-inf);S.insert(inf);
 78 //    printf("%d\n",S.size());
 79     for(edge *j=h[1];j;j=j->next)
 80     if(!v[j->t]){
 81     S.insert(j->v);
 82 //    printf("%d\n",S.size());
 83     }
 84     inc(i,1,tot)
 85     if(b[i]){
 86         it=S.upper_bound(b[i]);
 87         if(it==S.begin())continue;
 88         it--;
 89         S.erase(it);
 90 //        printf("%d\n",S.size());
 91         if(S.empty())return true;
 92     }
 93     return false;
 94  }
 95 int main(){
 96     n=read();
 97     inc(i,1,n-1){
 98         _x=read();_y=read();scanf("%lld",&_t);
 99         add(_x,_y,_t);add(_y,_x,_t);
100     }
101     dfs(1);
102     m=read();
103     inc(i,1,m)a[i]=read();
104     l=0;r=n*inf;
105     while(l+1<r){
106         _t=l+r>>1;
107         if(check())r=_t;else l=_t;
108     }
109     printf("%lld\n",r);
110     return 0;
111 }

时间: 2024-12-17 06:19:23

codevs 1218的相关文章

【CodeVS 1218】【NOIP 2012】疫情控制

http://codevs.cn/problem/1218/ 比较显然的倍增,但是对于跨过根需要很多讨论,总体思路是贪心. 写了一上午,不想再说什么了 #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long ll; const int N = 100003; int in() { int k = 0, fh = 1; char c = ge

疫情控制(codevs 1218)

题目描述 Description H 国有 n 个城市,这 n 个城市用 n-1 条双向道路相互连通构成一棵树,1 号城市是首都, 也是树中的根节点. H 国的首都爆发了一种危害性极高的传染病.当局为了控制疫情,不让疫情扩散到边境 城市(叶子节点所表示的城市),决定动用军队在一些城市建立检查点,使得从首都到边境 城市的每一条路径上都至少有一个检查点,边境城市也可以建立检查点.但特别要注意的是, 首都是不能建立检查点的. 现在,在 H国的一些城市中已经驻扎有军队,且一个城市可以驻扎多个军队.一支军

codevs 1218 疫情控制

啊好烦这道题.... 基本思路网上都有. 注意的一点是在匹配的时候,如果有军队的来源没有被匹配到,那么就先匹配这个来源.(因为不花钱). 不过数据好水.... #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxv 50050 #define maxe 100500 using namespace std; int n,x,y,z,g[max

[ CodeVS冲杯之路 ] P2492

不充钱,你怎么AC? 题目:http://codevs.cn/problem/2492/ 在此先orz小胖子,教我怎么路径压缩链表,那么这样就可以在任意节点跳进链表啦(手动@LCF) 对于查询操作,直接树状数组(以下简称BIT)维护,修改操作就一个个暴力开方搞,再用差值单点更新BIT 不过这样会TLE,要加一点优化对不对,正如开头所说的路径压缩链表 路径压缩链表其实就是个并查集,在普通的链表里,删去两个连续的节点后会是下面这种情况,如删去2,3 当访问 2 的时候,会跳到3,但 3 已经删除了,

[CODEVS 1281] Xn数列

描述 给你6个数,m, a, c, x0, n, g Xn+1 = ( aXn + c ) mod m,求Xn http://codevs.cn/problem/1281/ 分析 比较裸的矩阵乘法题, 好久没做了, 写写思路 假设矩阵 A = { {a1, a2}, {a3, a4} }, B = { {b1, b2}, {b3, b4} }. 根据矩阵乘法的计算方法, 有 : A×B = { {a1b1+a2b2, a1b2+a2b4}, {a3b1+a4b3, a3b2+a4b4} }. 那

Codevs 1257 打砖块

1257 打砖块 http://codevs.cn/problem/1257/ 题目描述 Description 在一个凹槽中放置了n层砖块,最上面的一层有n块砖,第二层有n-1块,……最下面一层仅有一块砖.第i层的砖块从左至右编号为1,2,……i,第i层的第j块砖有一个价值a[i,j](a[i,j]<=50).下面是一个有5层砖块的例子.如果你要敲掉第i层的第j块砖的话,若i=1,你可以直接敲掉它,若i>1,则你必须先敲掉第i-1层的第j和第j+1块砖. 你的任务是从一个有n(n<=5

codevs——T1219 骑士游历

 http://codevs.cn/problem/1219/ 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 查看运行结果 题目描述 Description 设有一个n*m的棋盘(2≤n≤50,2≤m≤50),如下图,在棋盘上有一个中国象棋马. 规定: 1)马只能走日字 2)马只能向右跳 问给定起点x1,y1和终点x2,y2,求出马从x1,y1出发到x2,y2的合法路径条数. 输入描述 Input Description 第一行2个整数n和m 第二行4个

1683 车厢重组 codevs

http://codevs.cn/problem/1683/ 时间限制: 1 s 空间限制: 1000 KB 题目等级 : 白银 Silver 题目描述 Description 在一个旧式的火车站旁边有一座桥,其桥面可以绕河中心的桥墩水平旋转.一个车站的职工发现桥的长度最多能容纳两节车厢,如果将桥旋转180度,则可以把相邻两节车厢的位置交换,用这种方法可以重新排列车厢的顺序.于是他就负责用这座桥将进站的车厢按车厢号从小到大排列.他退休后,火车站决定将这一工作自动化,其中一项重要的工作是编一个程序

codevs 1487 大批整数排序(水题日常)

时间限制: 3 s 空间限制: 16000 KB 题目等级 : 黄金 Gold 题目描述 Description !!!CodeVS开发者有话说: codevs自从换了评测机,新评测机的内存计算机制发生变化 计算内存的时候会包括栈空间 swap空间 这题的2M是单指内存空间... 十分十分抱歉 抱歉 !!! 现在有一大批(总数不超过10000000个)1到10之间的整数,现在请你从小到大进行排序输出. (测试数据将超过11MB.) 输入描述 Input Description 第一行表示将下排序