• 【LCA/tarjan】POJ1470-Closest Common Ancestors


    【题意】

    给出一棵树和多组查询,求以每个节点为LCA的查询数有多少?

    【错误点】

    ①读入的时候,注意它的空格是随意的呀!一开始不知道怎么弄,后来看了DISCUSS区大神的话:

    询问部分输入:

    scanf("%d",&m);
    for(int i=0;i<m;i++){
    scanf(" (%d %d)",&a,&b);
    }

    注意scanf(" 这里有一个空格

    ②多组数据啊!注意这句话:
    The input file contents several data sets (at least one).

    ③痛心疾首!它问的是以每个节点为LCA的查询数,所以查询可以重复,同样的查询可以累计!

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<vector>
      5 using namespace std;
      6 const int MAXN=900+5;
      7 vector<int> E[MAXN];
      8 int query[MAXN][MAXN];
      9 int cnt[MAXN];
     10 int notrt[MAXN],rt;
     11 int ance[MAXN];
     12 int vis[MAXN];
     13 int m;//结点的总个数 
     14 
     15 int find(int u)
     16 {
     17     int r=u;
     18     while (ance[r]!=r) r=ance[r];
     19     int ans=r;
     20     r=u;
     21     while (ance[r]!=r)
     22     {
     23         int tmp=ance[r];
     24         ance[r]=ans;
     25         r=tmp;
     26     }
     27     return ans;
     28 }
     29 
     30 void tarjan(int u)
     31 {
     32     vis[u]=1;
     33     for (int v=1;v<=m;v++)
     34     {
     35         if (!query[u][v]) continue;
     36         if (vis[v])
     37         //被访问过有两种情况:一是祖先靠左的子树中的后代;或者是自己的祖先。两者的LCA均为v所在并查集的根 
     38         {
     39             int LCA=find(v);
     40             cnt[LCA]+=query[u][v];
     41             //注意,允许同样的查询出现多次,并且同样的查询可以累计! 
     42         }
     43     }
     44     
     45     ance[u]=u;
     46     for (int i=0;i<E[u].size();i++)
     47     {
     48         int v=E[u][i];
     49         tarjan(v);
     50         ance[v]=u;
     51     }
     52 }
     53 
     54 void init()
     55 {
     56     memset(query,0,sizeof(query)); 
     57     memset(cnt,0,sizeof(cnt)); 
     58     memset(notrt,0,sizeof(notrt));
     59     memset(vis,0,sizeof(vis));
     60     for (int i=1;i<=m;i++) E[i].clear();
     61     for (int i=0;i<m;i++)
     62     {
     63         int p,T;
     64         scanf("%d:(%d)",&p,&T);
     65         for (int i=0;i<T;i++)
     66         {
     67             int son;
     68             scanf(" %d",&son);
     69             E[p].push_back(son);
     70             notrt[son]++;
     71         }
     72     } 
     73     
     74     int n;
     75     scanf("%d",&n); 
     76     for (int i=0; i<n; i++) 
     77     {
     78         int a,b;
     79         scanf(" (%d %d)",&a,&b);
     80         //注意这里(前面要有一个空格!否则无法过! 
     81         query[a][b]++;
     82         query[b][a]++;
     83     }
     84     
     85     for (int i=1;i<=m;i++) if (!notrt[i])
     86     {
     87         rt=i;
     88         break;
     89     } 
     90 }
     91 
     92 void print()
     93 {
     94     for (int i=1;i<=m;i++)
     95         if (cnt[i]>0)
     96             cout<<i<<':'<<cnt[i]<<endl;
     97 }
     98 
     99 int main()
    100 {
    101     while (~scanf("%d",&m)) 
    102     //注意是多组数据 
    103     {
    104         init();
    105         tarjan(rt);
    106         print();
    107     }
    108     return 0;
    109 }
  • 相关阅读:
    记一次 contentInsetAdjustmentBehavior 引发的bug
    Android埋点技术概览
    Android开发快速入门iOS开发概览
    工作项目遇到的一些问题
    ruby操作项目.xcodeproj
    关于performSelector afterDelay:0 的使用
    谷歌Python代码风格指南 中文翻译
    最大子矩阵问题--悬线法dp
    tarjan
    SDU CSPT3模拟
  • 原文地址:https://www.cnblogs.com/iiyiyi/p/5765688.html
Copyright © 2020-2023  润新知