【SPOJ】【1825】Free Tour 2
点分治
点分治的例题2(本题代码结果为TLE……)
强烈谴责卡时限QAQ,T了无数次啊无数次……
不过在N次的静态查错中倒是加深了对点分治的理解……也算因祸得福吧(自我安慰一下)
TLE后的改进:每棵子树在重算f数组的时候,不要完全清空,而是清到最深深度即可。——>WA
//SPOJ 1825
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
using namespace std;
inline void read(int &v){
v=; int sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
v*=sign;
}
/******************tamplate*********************/
const int N=,INF=1e8;
int n,m,k,root=,h[N],s[N],g[N],f[N],size,d[N];
bool vis[N],black[N];
int to[N],head[N],next[N],len[N],tot=;
inline void ins(int x,int y,int l){
to[++tot]=y; next[tot]=head[x]; head[x]=tot; len[tot]=l;
to[++tot]=x; next[tot]=head[y]; head[y]=tot; len[tot]=l;
} inline void getroot(int x,int fa){
s[x]=;h[x]=;
for(int i=head[x];i;i=next[i])
if (to[i]!=fa && !vis[to[i]]){
getroot(to[i],x);
s[x]+=s[to[i]];
//h[x]=max(h[x],s[to[i]]);
if (s[to[i]]>h[x]) h[x]=s[to[i]];
}
h[x]=max(h[x],size-s[x]);
if (h[x]<h[root]) root=x;
} inline void getdep(int x,int fa){
int res=;
for(int i=head[x];i;i=next[i]){
if (to[i]!=fa && !vis[to[i]]){
d[to[i]]=d[x]+black[to[i]];
getdep(to[i],x);
res=max(res,d[to[i]]);
}
}
d[x]+=res;
}
inline void getg(int x,int fa,int leng,int c){
g[c]=max(g[c],leng);
for(int i=head[x];i;i=next[i])
if (to[i]!=fa && !vis[to[i]]) getg(to[i],x,leng+len[i],c+black[to[i]]);
}
struct node{int deep,to,len;}st[N];
inline bool cmp(const node &a,const node &b) {return a.deep<b.deep;}
int ans=,cnt; void getans(int x){
vis[x]=;
for(int i=head[x];i;i=next[i])
getdep(to[i],x);
cnt=;
F(i,,n) f[i]=;
for(int i=head[x];i;i=next[i]){
if (!vis[to[i]]){
d[to[i]]=black[to[i]];
getdep(to[i],x);
st[cnt++]=(node){d[to[i]],to[i],len[i]};
}
}
sort(st,st+cnt,cmp);
rep(i,cnt){
int y=st[i].to;
F(j,,d[y]) g[j]=-INF;
getg(y,x,st[i].len,black[y]);
if (i>){
int end=min(k-black[x],d[y]);
F(j,,end){
int p=min(d[st[i-].to],k-j-black[x]);
if (f[p]==-INF) break;
if (g[j]!=-INF) ans=max(ans,g[j]+f[p]);
}
}
F(j,,d[y]){
f[j]=max(f[j],g[j]);
if (j) f[j]=max(f[j],f[j-]);
if (j+black[x]<=k) ans=max(ans,f[j]);
}
} for(int i=head[x];i;i=next[i])
if (!vis[to[i]]){
root=; size=s[to[i]];
getroot(to[i],x);
getans(root);
}
} int main(){
// freopen("1825.in","r",stdin);
read(n); read(k); read(m);
int x,y,l;
F(i,,m){ read(x); black[x]|=;}
F(i,,n){
read(x); read(y); read(l);
ins(x,y,l);
}
root=; size=n; h[root]=INF;
getroot(,);
getans(root);
printf("%d\n",ans);
return ;
}
WA:deep要反过来求,d[x]表示以x为根的子树中黑点最长的路径(而不是从root到x经过了多少黑点)
虽然好像原来的求法也能做不过不如这个方便(我一开始是写成两种混合了……QAQ)
RE:数组不能开20W,我改了个40W过了QAQ【iwtwiioi:双向边当然要开两倍的边集】!!!
//SPOJ 1825
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define rep(i,n) for(int i=0;i<n;++i)
#define F(i,j,n) for(int i=j;i<=n;++i)
#define D(i,j,n) for(int i=j;i>=n;--i)
using namespace std;
inline void read(int &v){
v=; int sign=; char ch=getchar();
while(ch<''||ch>''){ if (ch=='-') sign=-; ch=getchar();}
while(ch>=''&&ch<=''){ v=v*+ch-''; ch=getchar();}
v*=sign;
}
/******************tamplate*********************/
const int N=,INF=1e8;
int n,m,k,root=,h[N],s[N],g[N],f[N],size,d[N];
bool vis[N],black[N];
int to[N],head[N],next[N],len[N],tot=;
inline void ins(int x,int y,int l){
to[++tot]=y; next[tot]=head[x]; head[x]=tot; len[tot]=l;
to[++tot]=x; next[tot]=head[y]; head[y]=tot; len[tot]=l;
} inline void getroot(int x,int fa){
s[x]=;h[x]=;
for(int i=head[x];i;i=next[i])
if (to[i]!=fa && !vis[to[i]]){
getroot(to[i],x);
s[x]+=s[to[i]];
//h[x]=max(h[x],s[to[i]]);
if (s[to[i]]>h[x]) h[x]=s[to[i]];
}
h[x]=max(h[x],size-s[x]);
if (h[x]<h[root]) root=x;
} inline void getdep(int x,int fa){
int res=;
s[x]=; d[x]=black[x];
for(int i=head[x];i;i=next[i]){
if (to[i]!=fa && !vis[to[i]]){
getdep(to[i],x);
res=max(res,d[to[i]]);
s[x]+=s[to[i]];
}
}
d[x]+=res;//x为根的子树的最大“深度”
}
inline void getg(int x,int fa,int leng,int c){
g[c]=max(g[c],leng);
for(int i=head[x];i;i=next[i])
if (to[i]!=fa && !vis[to[i]])
getg(to[i],x,leng+len[i],c+black[to[i]]);
} inline bool cmp(int x,int y){
return d[to[x]]<d[to[y]];
}
int ans=,st[N],cnt; inline void getans(int x){
vis[x]=;//vis=1保证递归搜索子树时不会搜到当前节点
//对根的出边按dep排序
cnt=;
for(int i=head[x];i;i=next[i]){
if (!vis[to[i]]){
getdep(to[i],x);
st[cnt++]=i;
}
}
sort(st,st+cnt,cmp);
F(i,,d[to[st[cnt-]]]) f[i]=-INF;
rep(i,cnt){
int y=to[st[i]];
F(j,,d[y]) g[j]=-INF;
getg(y,x,len[st[i]],black[y]);
if (i>){
int end=min(k-black[x],d[y]);
F(j,,end){
int p=min(d[to[st[i-]]],k-j-black[x]);
if (f[p]==-INF) break;//!!!这里没懂
if (g[j]!=-INF) ans=max(ans,g[j]+f[p]);
}
}
F(j,,d[y]){
f[j]=max(f[j],g[j]);
if (j) f[j]=max(f[j],f[j-]);
if (j+black[x]<=k) ans=max(ans,f[j]);
}
} for(int i=head[x];i;i=next[i])
if (!vis[to[i]]){
root=; size=s[to[i]];
getroot(to[i],x);
getans(root);
}
} int main(){
#ifndef ONLINE_JUDGE
freopen("1825.in","r",stdin);
#endif
read(n); read(k); read(m);
int x,y,l;
F(i,,m){ read(x); black[x]|=;}
F(i,,n){
read(x); read(y); read(l);
ins(x,y,l);
}
root=; size=n; h[root]=INF;
getroot(,);
getans(root);
printf("%d\n",ans);
return ;
}
调了一天半终于出来了!锻炼了耐心和静态查错能力~
【SPOJ】【1825】Free Tour 2的更多相关文章
- 【SPOJ】1825. Free tour II(点分治)
http://www.spoj.com/problems/FTOUR2/ 先前看了一会题解就自己yy出来了...对拍过后交tle.................. 自己造了下大数据........t ...
- 【 SPOJ - GRASSPLA】 Grass Planting (树链剖分+树状数组)
54 种草约翰有 N 个牧场,编号为 1 到 N.它们之间有 N − 1 条道路,每条道路连接两个牧场.通过这些道路,所有牧场都是连通的.刚开始的时候,所有道路都是光秃秃的,没有青草.约翰会在一些道 ...
- 【SPOJ】NUMOFPAL - Number of Palindromes(Manacher,回文树)
[SPOJ]NUMOFPAL - Number of Palindromes(Manacher,回文树) 题面 洛谷 求一个串中包含几个回文串 题解 Manacher傻逼题 只是用回文树写写而已.. ...
- 【SPOJ】Substrings(后缀自动机)
[SPOJ]Substrings(后缀自动机) 题面 Vjudge 题意:给定一个长度为\(len\)的串,求出长度为1~len的子串中,出现最多的出现了多少次 题解 出现次数很好处理,就是\(rig ...
- 【SPOJ】Longest Common Substring II (后缀自动机)
[SPOJ]Longest Common Substring II (后缀自动机) 题面 Vjudge 题意:求若干个串的最长公共子串 题解 对于某一个串构建\(SAM\) 每个串依次进行匹配 同时记 ...
- 【SPOJ】Longest Common Substring(后缀自动机)
[SPOJ]Longest Common Substring(后缀自动机) 题面 Vjudge 题意:求两个串的最长公共子串 题解 \(SA\)的做法很简单 不再赘述 对于一个串构建\(SAM\) 另 ...
- 【SPOJ】Distinct Substrings(后缀自动机)
[SPOJ]Distinct Substrings(后缀自动机) 题面 Vjudge 题意:求一个串的不同子串的数量 题解 对于这个串构建后缀自动机之后 我们知道每个串出现的次数就是\(right/e ...
- 【SPOJ】Distinct Substrings/New Distinct Substrings(后缀数组)
[SPOJ]Distinct Substrings/New Distinct Substrings(后缀数组) 题面 Vjudge1 Vjudge2 题解 要求的是串的不同的子串个数 两道一模一样的题 ...
- 【SPOJ】Power Modulo Inverted(拓展BSGS)
[SPOJ]Power Modulo Inverted(拓展BSGS) 题面 洛谷 求最小的\(y\) 满足 \[k\equiv x^y(mod\ z)\] 题解 拓展\(BSGS\)模板题 #inc ...
- 【SPOJ】QTREE7(Link-Cut Tree)
[SPOJ]QTREE7(Link-Cut Tree) 题面 洛谷 Vjudge 题解 和QTREE6的本质是一样的:维护同色联通块 那么,QTREE6同理,对于两种颜色分别维护一棵\(LCT\) 每 ...
随机推荐
- NHibernate 错误
Unable to locate persister for the entity named 'Model.Customer'.The persister define the persistenc ...
- Gitlab Issue Tracker and Wiki(二)
一. 引用问题 1. 登陆 Gitlab服务器 2. 进入到super-git项目 3. 创建一个问题 4. 查看创建问题的号码,可以在下图找到. 5. 对代码进行提交去关闭这个问题,首先把项目在本机 ...
- 码云Android项目构建注意事项(转载)
1.ant项目 build.xml必须位于项目根目录. 2.maven项目 pom.xml必须位于项目根目录. 3.gradle项目 由于gradle的配置灵活,我们做了一些规范,并且增加了一下机制来 ...
- Adobe Photoshop CC 2017-18.0安装教程
Adobe Photoshop CC 2017-18.0安装教程 注:下载链接在文章后面 第一步:首先请将电脑的网络断开,很简单:禁用本地连接或者拔掉网线,这样就可以免除登录Creative Clou ...
- 分布式系统的烦恼------《Designing Data-Intensive Applications》读书笔记11
使用分布式系统与在单机系统中处理问题有很大的区别,分布式系统带来了更大的处理能力和存储容量之后,也带来了很多新的"烦恼".在这一篇之中,我们将看看分布式系统带给我们新的挑战. 1. ...
- MXNet——symbol
参考资料:有基础(Pytorch/TensorFlow基础)mxnet+gluon快速入门 symbol symbol 是一个重要的概念,可以理解为符号,就像我们平时使用的代数符号 x,y,z 一样. ...
- Graphviz 在 Windows 10 下 的 安装 Bug 解决方案
报错: 解决方法: 参考:stackoverflow
- 打开tcp_tw_recycle引起的一次投诉分析
背景: 我们有个基于oauth2.0协议给第三方授权以及信息的业务,年前对接入层.业务层做了次迁移.业务架构简单介绍下: lvs接入---> nginx ---> tomcat 问题: ...
- python 全排列
itertools模块现成的全排列: for i in itertools.permutations('abcd',4): print ''.join(i) 相关全排列算法: def perm(l): ...
- leetcode 无重复字符的最长子串 python实现
这道题需要借助哈希查找key的O(n) 时间复杂度, 否则就会超时 初始化一个 哈希表\字典 dic 头指针start 初始为0 当前指针 cur 初始为0 最大长度变量 l 初始为0 用cur变量 ...