【题意】
给出一棵树和多组查询,求以每个节点为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 }
时间: 2024-10-06 11:32:13