zoukankan      html  css  js  c++  java
  • poj1741+poj1987+poj2114——点分治入门题集合

    最近看了看点分治,从poj上找到几道题,都比较裸。而且感觉这三道题都长得差不多呀qwq

    ————————————————————————————————————————————————

    【poj 1741】Tree

    题意:给定一棵边带权的树,求两点之间的距离小于或等于K的点对个数。

    找重心,相当于把无根树转变为有根树。再利用分治的思想(根据经过重心或不经过重心来划分)。

    对于在同一个子树的情况要单独拎出来算并减去它们(因为是不该算在内的呀qwq)

    另外选取重心的好处是时间复杂度O(NlogN*logN),如果选取其他的点,不能保证会不会退化到O(N2*logN)

    //特别鸣谢,经@神犇gxz提醒,已改正刚才写时间复杂度的错误(大佬blog地址: http://www.cnblogs.com/GXZlegend/

      1 #include<cmath>
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 const int maxn=10010;
      6 using namespace std; 
      7 struct  Edge
      8 {
      9     int nxt;
     10     int to;
     11     int w;
     12     Edge(){}
     13     Edge(int _to,int _nxt,int _w):to(_to),nxt(_nxt),w(_w){}
     14 }edge[maxn<<1];
     15 int head[maxn],tot;
     16 void init()
     17 {
     18     memset(head,-1,sizeof(head));
     19     tot=0;
     20 }
     21 
     22 void AddEdge(int u,int v,int w)
     23 {
     24     
     25     edge[tot]=Edge(v,head[u],w);
     26     head[u]=tot++;
     27     edge[tot]=Edge(u,head[v],w);
     28     head[v]=tot++;
     29 }
     30 
     31 int son[maxn],siz[maxn],has[maxn],root;
     32 int n,K;
     33 void getroot(int u,int fa)
     34 {
     35     siz[u]=1;son[u]=0;
     36     for(int i=head[u];i!=-1;i=edge[i].nxt)
     37     {
     38         int v = edge[i].to;
     39         if(has[v]||v == fa) continue;
     40         getroot(v,u);
     41         siz[u] += siz[v];
     42         son[u] = max(son[u],siz[v]);
     43     }
     44     son[u] = max(son[u],son[0]-siz[u]);
     45     if(son[u]<son[root]) root=u;
     46 }
     47 int dis[maxn],res[maxn];
     48 void getdis(int u,int fa)
     49 {
     50     res[++res[0]]=dis[u];
     51     siz[u]=1;
     52     for(int i=head[u];i!=-1;i=edge[i].nxt)
     53     {
     54         int v=edge[i].to;
     55         if(has[v]||v==fa) continue;
     56         dis[v]=dis[u]+edge[i].w;
     57         getdis(v,u);
     58         siz[u]+=siz[v];
     59     }
     60 }
     61 int calc(int u,int init)//计算ans 
     62 {
     63     dis[u]=init;res[0]=0;getdis(u,u);
     64     sort(res+1,res+1+res[0]);
     65     int l=1,r=res[0];
     66     int ans=0;
     67     while(l<r)
     68     {
     69         if(res[l]+res[r]<=K)
     70             ans+=r-l++;
     71         else
     72             --r;
     73     }
     74     return ans;
     75 }
     76 int Ans;
     77 void dfs(int u)
     78 {
     79     Ans+=calc(u,0);
     80     has[u]=1;
     81     for(int i=head[u];i!=-1;i=edge[i].nxt)
     82     {
     83         int v=edge[i].to;
     84         if(has[v]) continue;
     85         Ans-=calc(v,edge[i].w);
     86         root=0;son[0]=siz[v];
     87         getroot(v,v);
     88         dfs(root);
     89     }
     90 }
     91 int main()
     92 {
     93     while(~scanf("%d%d",&n,&K))
     94     {
     95         int u,v,l;
     96         if(n+K==0) break; 
     97         init();
     98         memset(has,0,sizeof(has));
     99         for(int i=0;i<n-1;i++)
    100         {
    101             scanf("%d%d%d",&u,&v,&l);
    102             AddEdge(u,v,l);
    103         }
    104         root=0;son[0]=n;
    105         getroot(1,1);//找重心 
    106         Ans=0;
    107         dfs(root);
    108         printf("%d
    ",Ans);
    109     }
    110     return 0;
    111 }
    【poj1741】

    —————————————————————————————————————————————————

    【poj 1987】

    和1741基本是一样一样的,无脑复制就好啦つ﹏⊂

    不过稍微注意一下,要记得用%*d或%*s跳过多余的输入。

      1 #include<cmath>
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 const int maxn=40010;
      6 using namespace std; 
      7 struct  Edge
      8 {
      9     int nxt;
     10     int to;
     11     int w;
     12     Edge(){}
     13     Edge(int _to,int _nxt,int _w):to(_to),nxt(_nxt),w(_w){}
     14 }edge[maxn<<1];
     15 int head[maxn],tot;
     16 void init()
     17 {
     18     memset(head,-1,sizeof(head));
     19     tot=0;
     20 }
     21 
     22 void AddEdge(int u,int v,int w)
     23 {
     24     
     25     edge[tot]=Edge(v,head[u],w);
     26     head[u]=tot++;
     27     edge[tot]=Edge(u,head[v],w);
     28     head[v]=tot++;
     29 }
     30 
     31 int son[maxn],siz[maxn],has[maxn],root;
     32 int n,K;
     33 void getroot(int u,int fa)
     34 {
     35     siz[u]=1;son[u]=0;
     36     for(int i=head[u];i!=-1;i=edge[i].nxt)
     37     {
     38         int v = edge[i].to;
     39         if(has[v]||v == fa) continue;
     40         getroot(v,u);
     41         siz[u] += siz[v];
     42         son[u] = max(son[u],siz[v]);
     43     }
     44     son[u] = max(son[u],son[0]-siz[u]);
     45     if(son[u]<son[root]) root=u;
     46 }
     47 int dis[maxn],res[maxn];
     48 void getdis(int u,int fa)
     49 {
     50     res[++res[0]]=dis[u];
     51     siz[u]=1;
     52     for(int i=head[u];i!=-1;i=edge[i].nxt)
     53     {
     54         int v=edge[i].to;
     55         if(has[v]||v==fa) continue;
     56         dis[v]=dis[u]+edge[i].w;
     57         getdis(v,u);
     58         siz[u]+=siz[v];
     59     }
     60 }
     61 int calc(int u,int init)//计算ans 
     62 {
     63     dis[u]=init;res[0]=0;getdis(u,u);
     64     sort(res+1,res+1+res[0]);
     65     int l=1,r=res[0];
     66     int ans=0;
     67     while(l<r)
     68     {
     69         if(res[l]+res[r]<=K)
     70             ans+=r-l++;
     71         else
     72             --r;
     73     }
     74     return ans;
     75 }
     76 int Ans;
     77 void dfs(int u)
     78 {
     79     Ans+=calc(u,0);
     80     has[u]=1;
     81     for(int i=head[u];i!=-1;i=edge[i].nxt)
     82     {
     83         int v=edge[i].to;
     84         if(has[v]) continue;
     85         Ans-=calc(v,edge[i].w);
     86         root=0;son[0]=siz[v];
     87         getroot(v,v);
     88         dfs(root);
     89     }
     90 }
     91 int main()
     92 {
     93     while(~scanf("%d%*d",&n))
     94     {
     95         int u,v,l;
     96         if(n+K==0) break; 
     97         init();
     98         memset(has,0,sizeof(has));
     99         for(int i=0;i<n-1;i++)
    100         {
    101             scanf("%d%d%d%*s",&u,&v,&l);
    102             AddEdge(u,v,l);
    103         }
    104         scanf("%d",&K);
    105         root=0;son[0]=n;
    106         getroot(1,1);
    107         Ans=0;
    108         dfs(root);
    109         printf("%d
    ",Ans);
    110     }
    111     return 0;
    112 }
    【poj 1987】

    —————————————————————————————————————————————————

    【poj 2114】

    题意:给定一棵边带权的树,求两点之间的距离刚好等于K的情况是否存在。

      1 #include<cmath>
      2 #include<iostream>
      3 #include<algorithm>
      4 #include<cstring>
      5 const int maxn=10010;
      6 using namespace std; 
      7 struct  Edge
      8 {
      9     int nxt;
     10     int to;
     11     int w;
     12     Edge(){}
     13     Edge(int _to,int _nxt,int _w):to(_to),nxt(_nxt),w(_w){}
     14 }edge[maxn<<1];
     15 int head[maxn],tot;
     16 void init()
     17 {
     18     memset(head,-1,sizeof(head));
     19     tot=0;
     20 }
     21 
     22 void AddEdge(int u,int v,int w)
     23 {
     24     
     25     edge[tot]=Edge(v,head[u],w);
     26     head[u]=tot++;
     27     edge[tot]=Edge(u,head[v],w);
     28     head[v]=tot++;
     29 }
     30 
     31 int son[maxn],siz[maxn],has[maxn],root;
     32 int n,K;
     33 void getroot(int u,int fa)
     34 {
     35     siz[u]=1;son[u]=0;
     36     for(int i=head[u];i!=-1;i=edge[i].nxt)
     37     {
     38         int v = edge[i].to;
     39         if(has[v]||v == fa) continue;
     40         getroot(v,u);
     41         siz[u] += siz[v];
     42         son[u] = max(son[u],siz[v]);
     43     }
     44     son[u] = max(son[u],son[0]-siz[u]);
     45     if(son[u]<son[root]) root=u;
     46 }
     47 int dis[maxn],res[maxn];
     48 void getdis(int u,int fa)
     49 {
     50     res[++res[0]]=dis[u];
     51     siz[u]=1;
     52     for(int i=head[u];i!=-1;i=edge[i].nxt)
     53     {
     54         int v=edge[i].to;
     55         if(has[v]||v==fa) continue;
     56         dis[v]=dis[u]+edge[i].w;
     57         getdis(v,u);
     58         siz[u]+=siz[v];
     59     }
     60 }
     61 int calc(int u,int init)//计算ans 
     62 {
     63     dis[u]=init;res[0]=0;getdis(u,u);
     64     sort(res+1,res+1+res[0]);
     65     int l=1,r=res[0];
     66     int ans=0;
     67     while (l<r)
     68     {
     69         if(res[l]+res[r]==K) 
     70         {
     71             if (res[l]==res[r]) 
     72             {
     73                 ans+=(r-l+1)*(r-l)/2;
     74                 break;
     75             }
     76             int i=l,j=r;
     77             while(res[l]==res[i]) ++i;
     78             while(res[r]==res[j]) --j;
     79             ans+=(i-l)*(r-j);
     80             l=i,r=j;
     81         }
     82         else if (res[l]+res[r]>K) r--;
     83         else  l++;
     84     }
     85     return ans;
     86 }
     87 int Ans;
     88 void dfs(int u)
     89 {
     90     has[u]=1;
     91     Ans+=calc(u,0);
     92     for(int i=head[u];i!=-1;i=edge[i].nxt)
     93     {
     94         int v=edge[i].to;
     95         if(has[v]) continue;
     96         Ans-=calc(v,edge[i].w);
     97         root=0;son[0]=siz[v];
     98         getroot(v,v);
     99         dfs(root);
    100     }
    101 }
    102 
    103 int main()
    104 {
    105     while(~scanf("%d",&n)&&n) 
    106     {
    107         int x,c;
    108         init();
    109         for(int i=1;i<=n;i++)
    110         {
    111             while(~scanf("%d",&x)&&x)
    112             {
    113                 scanf("%d",&c);
    114                 AddEdge(i,x,c);
    115             //    AddEdge(x,i,c);不用再反着存一遍了qwq 
    116             }
    117         }
    118         while(~scanf("%d",&K)&&K)
    119         {
    120             memset(has,0,sizeof(has));
    121             Ans=root=0;
    122             son[0]=n;
    123             getroot(1,1);
    124             dfs(root);
    125             printf(Ans?"AYE
    ":"NAY
    "); 
    126         }
    127         puts(".");
    128     }
    129     return 0;
    130 }
    131 /*
    132 6
    133 2 5 3 7 4 1 0
    134 0
    135 5 2 6 3 0
    136 0
    137 0
    138 0
    139 1
    140 8
    141 13
    142 14
    143 0
    144 0
    145 */
    【poj 2114】

    ———————————————————————————————————————————————

    /*

    qwq就是这个题奇奇怪怪调了好久

    跟机房dalao1号求助

    dalao1号说这么长啊你给dalao2号吧

    发给dalao2号

    dalao2号看了一会儿说

    我也看不出来你哪写错了你给dalao3号吧

    于是发给dalao3号

    dalao3号一看题目

    愣了几秒说我可没写过点分治啊

    ……于是发给jdfz的dalao4号

    dalao4号说你可以这样这样写

    我按dalao4号的改了改发现还是TLE

    实在没辙了qwq

    最后某只Au爷说帮我看

    过了几分钟……

    Au爷:“来来来,我保证不打死你”

    我:“啊啊啊不要打我啊我错了……”

    被发现是把树存了4遍……

    用了前向星存

    addedge函数里

    我自己写了正着和反着加

    结果main函数里读入时又存了两遍

    所以才崩了啊啊啊

    血与泪的教训

    以后不能犯了(碎碎念qwq)

    */

  • 相关阅读:
    关于const_cast
    TinyXPath与TinyXML
    C++的异常
    如何让对象只能处于堆中
    股票的委托价、成交价与成本价的关系
    static_cast dynamic_cast reinterpret_cast const_cast
    C++ MD5,SHA1源码下载和简单调用
    C++中char[]转string
    HttpWorker
    winnet winhttp
  • 原文地址:https://www.cnblogs.com/Beckinsale/p/7066949.html
Copyright © 2011-2022 走看看