【SPOJ】【1825】Free Tour 2

点分治

  点分治的例题2(本题代码结果为TLE……)

  强烈谴责卡时限QAQ,T了无数次啊无数次……

  不过在N次的静态查错中倒是加深了对点分治的理解……也算因祸得福吧(自我安慰一下)

 

TLE后的改进:每棵子树在重算f数组的时候,不要完全清空,而是清到最深深度即可。——>WA

  1 //SPOJ 1825
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<iostream>
  6 #include<algorithm>
  7 #define rep(i,n) for(int i=0;i<n;++i)
  8 #define F(i,j,n) for(int i=j;i<=n;++i)
  9 #define D(i,j,n) for(int i=j;i>=n;--i)
 10 using namespace std;
 11 inline void read(int &v){
 12     v=0; int sign=1; char ch=getchar();
 13     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
 14     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
 15     v*=sign;
 16 }
 17 /******************tamplate*********************/
 18 const int N=200010,INF=1e8;
 19 int n,m,k,root=0,h[N],s[N],g[N],f[N],size,d[N];
 20 bool vis[N],black[N];
 21 int to[N],head[N],next[N],len[N],tot=0;
 22 inline void ins(int x,int y,int l){
 23     to[++tot]=y; next[tot]=head[x]; head[x]=tot; len[tot]=l;
 24     to[++tot]=x; next[tot]=head[y]; head[y]=tot; len[tot]=l;
 25 }
 26 
 27 inline void getroot(int x,int fa){
 28     s[x]=1;h[x]=0;
 29     for(int i=head[x];i;i=next[i])
 30         if (to[i]!=fa && !vis[to[i]]){
 31             getroot(to[i],x);
 32             s[x]+=s[to[i]];
 33             //h[x]=max(h[x],s[to[i]]);
 34             if (s[to[i]]>h[x]) h[x]=s[to[i]];
 35         }
 36     h[x]=max(h[x],size-s[x]);
 37     if (h[x]<h[root]) root=x;
 38 }
 39 
 40 inline void getdep(int x,int fa){
 41     int res=0;
 42     for(int i=head[x];i;i=next[i]){
 43         if (to[i]!=fa && !vis[to[i]]){
 44             d[to[i]]=d[x]+black[to[i]];
 45             getdep(to[i],x);
 46             res=max(res,d[to[i]]);
 47         }
 48     }
 49     d[x]+=res;
 50 }
 51 inline void getg(int x,int fa,int leng,int c){
 52     g[c]=max(g[c],leng);
 53     for(int i=head[x];i;i=next[i])
 54         if (to[i]!=fa && !vis[to[i]]) getg(to[i],x,leng+len[i],c+black[to[i]]);
 55 }
 56 struct node{int deep,to,len;}st[N];
 57 inline bool cmp(const node &a,const node &b) {return a.deep<b.deep;}
 58 int ans=0,cnt;
 59 
 60 void getans(int x){
 61     vis[x]=1;
 62     for(int i=head[x];i;i=next[i])
 63         getdep(to[i],x);
 64     cnt=0;
 65     F(i,0,n) f[i]=0;
 66     for(int i=head[x];i;i=next[i]){
 67         if (!vis[to[i]]){
 68             d[to[i]]=black[to[i]];
 69             getdep(to[i],x);
 70             st[cnt++]=(node){d[to[i]],to[i],len[i]};
 71         }
 72     }
 73     sort(st,st+cnt,cmp);
 74     rep(i,cnt){
 75         int y=st[i].to;
 76         F(j,0,d[y]) g[j]=-INF;
 77         getg(y,x,st[i].len,black[y]);
 78         if (i>0){
 79             int end=min(k-black[x],d[y]);
 80             F(j,0,end){
 81                 int p=min(d[st[i-1].to],k-j-black[x]);
 82                 if (f[p]==-INF) break;
 83                 if (g[j]!=-INF) ans=max(ans,g[j]+f[p]);
 84             }
 85         }
 86         F(j,0,d[y]){
 87             f[j]=max(f[j],g[j]);
 88             if (j) f[j]=max(f[j],f[j-1]);
 89             if (j+black[x]<=k) ans=max(ans,f[j]);
 90         }
 91     }
 92     
 93     for(int i=head[x];i;i=next[i])
 94         if (!vis[to[i]]){
 95             root=0; size=s[to[i]];
 96             getroot(to[i],x);
 97             getans(root);
 98         }
 99 }
100 
101 int main(){
102 //    freopen("1825.in","r",stdin);
103     read(n); read(k); read(m);
104     int x,y,l;
105     F(i,1,m){ read(x); black[x]|=1;}
106     F(i,2,n){
107         read(x); read(y); read(l);
108         ins(x,y,l);
109     }
110     root=0; size=n; h[root]=INF;
111     getroot(1,0);
112     getans(root);
113     printf("%d\n",ans);
114     return 0;
115 }
View Code

WA:deep要反过来求,d[x]表示以x为根的子树中黑点最长的路径(而不是从root到x经过了多少黑点)

  虽然好像原来的求法也能做不过不如这个方便(我一开始是写成两种混合了……QAQ)

 RE:数组不能开20W,我改了个40W过了QAQ【iwtwiioi:双向边当然要开两倍的边集】!!!

  1 //SPOJ 1825
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<iostream>
  6 #include<algorithm>
  7 #define rep(i,n) for(int i=0;i<n;++i)
  8 #define F(i,j,n) for(int i=j;i<=n;++i)
  9 #define D(i,j,n) for(int i=j;i>=n;--i)
 10 using namespace std;
 11 inline void read(int &v){
 12     v=0; int sign=1; char ch=getchar();
 13     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
 14     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
 15     v*=sign;
 16 }
 17 /******************tamplate*********************/
 18 const int N=400010,INF=1e8;
 19 int n,m,k,root=0,h[N],s[N],g[N],f[N],size,d[N];
 20 bool vis[N],black[N];
 21 int to[N],head[N],next[N],len[N],tot=0;
 22 inline void ins(int x,int y,int l){
 23     to[++tot]=y; next[tot]=head[x]; head[x]=tot; len[tot]=l;
 24     to[++tot]=x; next[tot]=head[y]; head[y]=tot; len[tot]=l;
 25 }
 26 
 27 inline void getroot(int x,int fa){
 28     s[x]=1;h[x]=0;
 29     for(int i=head[x];i;i=next[i])
 30         if (to[i]!=fa && !vis[to[i]]){
 31             getroot(to[i],x);
 32             s[x]+=s[to[i]];
 33             //h[x]=max(h[x],s[to[i]]);
 34             if (s[to[i]]>h[x]) h[x]=s[to[i]];
 35         }
 36     h[x]=max(h[x],size-s[x]);
 37     if (h[x]<h[root]) root=x;
 38 }
 39 
 40 inline void getdep(int x,int fa){
 41     int res=0;
 42     s[x]=1; d[x]=black[x];
 43     for(int i=head[x];i;i=next[i]){
 44         if (to[i]!=fa && !vis[to[i]]){
 45             getdep(to[i],x);
 46             res=max(res,d[to[i]]);
 47             s[x]+=s[to[i]];
 48         }
 49     }
 50     d[x]+=res;//x为根的子树的最大“深度”
 51 }
 52 inline void getg(int x,int fa,int leng,int c){
 53     g[c]=max(g[c],leng);
 54     for(int i=head[x];i;i=next[i])
 55         if (to[i]!=fa && !vis[to[i]]) 
 56             getg(to[i],x,leng+len[i],c+black[to[i]]);
 57 }
 58 
 59 inline bool cmp(int x,int y){
 60     return d[to[x]]<d[to[y]];
 61 }
 62 int ans=0,st[N],cnt;
 63 
 64 inline void getans(int x){
 65     vis[x]=1;//vis=1保证递归搜索子树时不会搜到当前节点
 66     //对根的出边按dep排序
 67     cnt=0;
 68     for(int i=head[x];i;i=next[i]){
 69         if (!vis[to[i]]){
 70             getdep(to[i],x);
 71             st[cnt++]=i;
 72         }
 73     }
 74     sort(st,st+cnt,cmp);
 75     F(i,0,d[to[st[cnt-1]]]) f[i]=-INF;
 76     rep(i,cnt){
 77         int y=to[st[i]];
 78         F(j,0,d[y]) g[j]=-INF;
 79         getg(y,x,len[st[i]],black[y]);
 80         if (i>0){
 81             int end=min(k-black[x],d[y]);
 82             F(j,0,end){
 83                 int p=min(d[to[st[i-1]]],k-j-black[x]);
 84                 if (f[p]==-INF) break;//!!!这里没懂
 85                 if (g[j]!=-INF) ans=max(ans,g[j]+f[p]);
 86             }
 87         }
 88         F(j,0,d[y]){
 89             f[j]=max(f[j],g[j]);
 90             if (j) f[j]=max(f[j],f[j-1]);
 91             if (j+black[x]<=k) ans=max(ans,f[j]);
 92         }
 93     }
 94     
 95     for(int i=head[x];i;i=next[i])
 96         if (!vis[to[i]]){
 97             root=0; size=s[to[i]];
 98             getroot(to[i],x);
 99             getans(root);
100         }
101 }
102 
103 int main(){
104 #ifndef ONLINE_JUDGE
105     freopen("1825.in","r",stdin);
106 #endif
107     read(n); read(k); read(m);
108     int x,y,l;
109     F(i,1,m){ read(x); black[x]|=1;}
110     F(i,2,n){
111         read(x); read(y); read(l);
112         ins(x,y,l);
113     }
114     root=0; size=n; h[root]=INF;
115     getroot(1,0);
116     getans(root);
117     printf("%d\n",ans);
118     return 0;
119 }
View Code

调了一天半终于出来了!锻炼了耐心和静态查错能力~

posted @ 2015-01-20 23:28  Tunix  阅读(484)  评论(0编辑  收藏  举报