COGS2109 http://cogs.pro:8080/cogs/problem/problem.php?pid=2109

洛谷交上去一直CE啊好绝望

COGS交了90分,一个点WA,一个点TLE嘤嘤嘤

恕我是在找不出来错误了

思路


先算LCA,深度,父节点什么的

二分答案,然后我们贪心的验证:

先找出所有应该改小的路径,记录个数和最大值,并差分地标记在在树上

随后DFS,找出所有应改小的路径都经过的边,即查询差分的值等于前面记录的个数的边

如果没找到,说明答案太苛刻了,放松一点

如果找到了,决定去掉其中权最大的那条边

如果这条边能让最长的路径合法,说明其他路径皆能合法,收紧答案

否则放松答案

然后完了,然而并不知道哪里错了

卡常好恶心

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 300010
 4 inline bool isitdigit(char c){return c<='9'&&c>='0';}
 5 inline int maintain(int &a,int b){ return a>b?a:a=b;}
 6 inline int read()
 7 {
 8     register int s;register char c;
 9     while(!isitdigit(c=getchar()));
10     for(s=c-'0';isitdigit(c=getchar());s=(s<<1)+(s<<3)+c-'0');
11     return s;
12 }
13 int findset[N];
14 inline int find(int x){return x==findset[x]? x:findset[x]=find(findset[x]);}
15 inline int merge(int a,int b){return find(a)==find(b)?0:findset[findset[a]]=findset[b];}
16 int n,m;
17 int head[N],to[N*2],next[N*2],value[N*2],tot;
18 struct ask{
19     int v,u,lca,dis;
20 }road[N];
21 int u[2*N],v[2*N],linking[2*N],enter[N],dis[N],deep[N],lca[2*N],cnt,maxdis,mark[N],father[N],maxside;
22 inline void add(int f,int t,int v){to[++tot]=t;value[tot]=v;next[tot]=head[f];head[f]=tot;}
23 inline void conect(int f,int t){u[++cnt]=f;v[cnt]=t;linking[cnt]=enter[f];enter[f]=cnt;}
24 void tarjan(int i,int f,int d)
25 {
26     father[i]=f;
27     deep[i]=d;
28     for(register int j=head[i];j;j=next[j]) if(to[j]!=f)
29     {
30         tarjan(to[j],i,d+value[j]);
31         merge(to[j],i);
32     }
33     for(register int j=enter[i];j;j=linking[j]) if(~deep[v[j]]) lca[j]=find(v[j]);
34 }
35 int dfs(int i,int f,int v)
36 {
37     int d=mark[i];
38     for(register int j=head[i];j;j=next[j]) if(to[j]!=f) d+=dfs(to[j],i,value[j]);
39     if(d==cnt) maintain(maxside,v);
40     return d;
41 }
42
43 inline bool cal(int ans)
44 {
45     cnt=maxdis=maxside=0;
46     memset(mark,0,sizeof(mark));
47     for(register int i=1;i<=m;++i) if(road[i].dis>ans)
48     {
49         cnt++,maintain(maxdis,road[i].dis);
50         mark[father[road[i].lca]]-=2;
51         mark[road[i].u]++,mark[road[i].v]++;
52     }
53
54     dfs(1,0,0);
55     return maxdis-maxside<=ans;
56 }
57
58
59 int main()
60 {
61     freopen("transport.in","r",stdin);
62     freopen("transport.out","w",stdout);
63     memset(deep,0xff,sizeof(deep));
64     n=read(),m=read();
65     for(register int i=1;i<=n;++i) findset[i]=i;
66     for(register int i=1;i<n;++i)
67     {
68         int f=read();int t=read();int v=read();
69         add(f,t,v),add(t,f,v);
70     }
71     for(register int i=1;i<=m;++i)
72     {
73         int f=read();int t=read();
74         conect(f,t),conect(t,f);
75     }
76     tarjan(1,0,0);
77     for(register int i=2;i<=cnt;i+=2) lca[i]==0? lca[i]=lca[i-1]:lca[i];
78     for(register int i=2;i<=cnt;i+=2) road[i>>1]=(ask){v[i],u[i],lca[i],deep[u[i]]+deep[v[i]]-(deep[lca[i]]<<1)};
79     int l=0,r=1000*n;
80     while(l<r)
81     {
82         int mid=(l+r)>>1;
83         if(cal(mid))r=mid;
84             else l=mid+1;
85     }
86     printf("%d",l);
87     return 0;
88 }

 更新

把DFS改成DFS序好了,虽说BFS序理论上好一点,但是懒得写了

错误原因是在LCA的父节点上打了差分标记,这样就忽略了指向LCA的那条边,所以应该在LCA本身打标记

坑啊,改完后AC

#include<bits/stdc++.h>
using namespace std;
#define N 300010
inline bool isitdigit(char c){return c<='9'&&c>='0';}
inline int maintain(int &a,int b){ return a>b?a:a=b;}
inline int read()
{register int s;register char c;while(!isitdigit(c=getchar()));for(s=c-'0';isitdigit(c=getchar());s=(s<<1)+(s<<3)+c-'0');return s;
}
int findset[N];
inline int find(int x){return x==findset[x]? x:findset[x]=find(findset[x]);}
inline int merge(int a,int b){return find(a)==find(b)?0:findset[findset[a]]=findset[b];}
int n,m;
int head[N],to[N*2],next[N*2],value[N*2],tot,order[N],idx,edge[N];
struct ask{int v,u,lca,dis;
}road[N];
int u[2*N],v[2*N],linking[2*N],enter[N],dis[N],deep[N],lca[2*N],cnt,maxdis,mark[N],father[N],maxside;
inline void add(int f,int t,int v){to[++tot]=t;value[tot]=v;next[tot]=head[f];head[f]=tot;}
inline void conect(int f,int t){u[++cnt]=f;v[cnt]=t;linking[cnt]=enter[f];enter[f]=cnt;}
void tarjan(int i,int f,int d,int side)
{edge[i]=side;order[++idx]=i;father[i]=f;deep[i]=d;for(register int j=head[i];j;j=next[j]) if(to[j]!=f){tarjan(to[j],i,d+value[j],value[j]);merge(to[j],i);}for(register int j=enter[i];j;j=linking[j]) if(deep[v[j]]!=-1) lca[j]=find(v[j]);
}inline bool cal(int ans)
{cnt=maxdis=maxside=0;memset(mark,0,sizeof(mark));for(register int i=1;i<=m;++i) if(road[i].dis>ans) {cnt++,maintain(maxdis,road[i].dis);mark[road[i].lca]-=2;mark[road[i].u]++,mark[road[i].v]++;}for(register int i=idx;i>=1;--i) mark[father[order[i]]]+=mark[order[i]];for(register int i=1;i<=n;++i) if(mark[i]==cnt) maintain(maxside,edge[i]);return maxdis-maxside<=ans;
}int main()
{    freopen("transport.in","r",stdin);freopen("transport.out","w",stdout);memset(deep,0xff,sizeof(deep));n=read(),m=read();for(register int i=1;i<=n;++i) findset[i]=i;for(register int i=1;i<n;++i) {int f=read();int t=read();int v=read();add(f,t,v),add(t,f,v);}for(register int i=1;i<=m;++i) {int f=read();int t=read();conect(f,t),conect(t,f);}tarjan(1,0,0,0);for(register int i=2;i<=cnt;i+=2) lca[i]==0? lca[i]=lca[i-1]:lca[i];for(register int i=2;i<=cnt;i+=2) road[i>>1]=(ask){v[i],u[i],lca[i],deep[u[i]]+deep[v[i]]-(deep[lca[i]]<<1)}; int l=0,r=1000*n;while(l<r){int mid=(l+r)>>1;if(cal(mid))r=mid;else l=mid+1;}printf("%d",l);return 0;
}

转载于:https://www.cnblogs.com/MediocreKonjac/p/9101859.html

NOIP2015运输计划相关推荐

  1. BZOJ 4326 NOIP2015 运输计划(树上差分+LCA+二分答案)

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MB Submit: 1388  Solved: 860 [Submit][Stat ...

  2. cogs2109 [NOIP2015] 运输计划

    cogs2109 [NOIP2015] 运输计划 二分答案+树上差分. STO链剖巨佬们我不会(太虚伪了吧 首先二分一个答案,下界为0,上界为max{路径长度}. 然后判断一个答案是否可行,这里用到树 ...

  3. 洛谷 2680 (NOIp2015) 运输计划

    题目:https://www.luogu.org/problemnew/show/P2680 因为是最长的时间最短,所以二分! 离线LCA可以知道路径长度.每次只看超过二分值的路径. 原本的想法是遍历 ...

  4. $Luogu2680/NOIp2015$ 运输计划

    传送门 $Sol$ 最暴力的做法就是枚举最长链上的边,然后再算一次所有的链长,更新$ans$. 这里要求最大的最小,容易想到二分答案.对于二分的值$mid$,扫一遍所有的链,若链长小于等于$mid$, ...

  5. 【图论】【LCA】NOIP2015运输计划

    分析: mmp出题人太垃圾了 尼玛树链剖分 O(Nlog2N) O ( N l o g 2 N ) O(Nlog^2N)的算法跑得飞快,用LCA严格 O(NlogN) O ( N l o g N ) ...

  6. 【Bzoj4326】运输计划

    4326: NOIP2015 运输计划 Time Limit: 30 Sec  Memory Limit: 128 MB Submit: 1091  Solved: 696 [Submit][Stat ...

  7. [NOIP2015提高组]运输计划

    题目:BZOJ4326.洛谷P2680.Vijos P1983.UOJ#150.codevs4632.codevs5440. 题目大意:有一棵带权树,有一些运输计划,第i个运输计划从ai到bi,耗时为 ...

  8. UOJ #150 【NOIP2015】 运输计划

    题目描述 公元 \(2044\) 年,人类进入了宇宙纪元. \(L\) 国有 \(n\) 个星球,还有 \(n-1\) 条双向航道,每条航道建立在两个星球之间,这 \(n-1\) 条航道连通了 \(L ...

  9. [NOIP 2015]运输计划-[树上差分+二分答案]-解题报告

    [NOIP 2015]运输计划 题面: A[NOIP2015 Day2]运输计划 时间限制 : 20000 MS 空间限制 : 262144 KB 问题描述 公元 2044 年,人类进入了宇宙纪元. ...

  10. P2680 运输计划(树上差分+lca+二分)

    题目背景 公元 20442044 年,人类进入了宇宙纪元. 题目描述 公元20442044 年,人类进入了宇宙纪元. L 国有 nn 个星球,还有 n-1n−1 条双向航道,每条航道建立在两个星球之间 ...

最新文章

  1. list group by java_Java List集合实现MySQL Group By功能
  2. Java基础day24
  3. 从上往下打印出二叉树的每个节点,同层节点从左至右打印
  4. 使用screen -r时提示“There is no screen to be resumed matching xxx”的解决办法
  5. 计算机b级英语翻译,英语B级考试翻译必备常用短句
  6. VC++的dll中接收消息
  7. php create()方法,ThinkPHP中create()方法自动验证实例
  8. 大数据与大量数据处理_我们如何处理和使用如此大量的数据?
  9. 好用的pdf预览插件
  10. rango php,韩天峰(Rango)的博客
  11. [转]Git,SVN的优缺点及适合的范围,开源项目?公司项目?
  12. 使用Delphi创建,解析,操纵XML文档
  13. ArcGIS操作小技巧(五)之色带-----横向(水平)图例
  14. php课程设计学生信息管理系统,学生成绩管理系统/学生信息管理系统
  15. 背包九讲(例题+代码)
  16. 难得一见的数据库事务异常 Deadlock found when trying to get lock解决办法dao.DeadlockLoserDataAccessException怎么办
  17. python金融分析培训课程_Python金融分析相关书籍推荐
  18. iOS中流媒体【视频】播放和下载【用到第三方的助手类】
  19. mysql 系统默认_mysql之系统默认数据库
  20. 输入3×4的矩阵 将值为负的位置和值输出

热门文章

  1. 内推 | 高级数据分析师(base:杭州)
  2. datagrip 自动展示库名_DataGrip 2018.1.4 功能强大的多引擎数据库管理工具
  3. 安装CentOS7虚拟机
  4. Android找工作系列之事件传递机制
  5. php的json_encode第二个参数学习及应用
  6. win10环境下MinGW和MSYS的安装与配置
  7. JAVA 8 :从永久区(PermGen)到元空间(Metaspace)
  8. 关于ajax表单提交.serialize()
  9. Ubuntu下Hadoop的安装和配置
  10. 【推荐】一个移动开发的网站