HDU 5923 Prediction [可持久化并查集]【数据结构】
题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=5923 Time Limit: 5000/2500 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description Each vertex of the magic tree corresponds to an edge in the original graph G and each edge occurs in the magic tree exactly once. Each query includes a set S(S?VT),and you should tell Mr. Frog the number of components in the modified graph G‘=(VG,E‘G),where E‘G is a set of edges in which every edge corresponds to a vertex v in magic tree T satisfying at least one of the following two conditions: ?v∈S. Note that the queries are independent,and namely one query will not influence another. Input For each test case,the first line contains two integers n and m(1≤n≤500,1≤m≤10000),where n is the number of vertices and m is the number of edges. The second line contains m - 1 integers describing the magic tree,i-th integer represents the parent of the (i + 1)-th vertex. Then the following m lines describe the edges of the graph G. Each line contains two integers u and v indicating the two ends of the edge. The next line contains only one integer q(1≤q≤50000),indicating the number of queries. Then the following q lines represent queries,i-th line represents the i-th query,which contains an integer ki followed by ki integers representing the set Si. It is guarenteed that
Output For each query,output a single line containing only one integer representing the answer,namely the number of components. Sample Input Sample Output Hint magic tree and the original graph in the sample are: In the first query,S = {2} and the modified graph G’ = {{1,2,3,4},{(1,2),(2,3)}},thus the number of the components in the modified graph is 3. 题目大意: 解题思路: 之后在对图进行并查集的操作,来统计有几个联通块就行了。 在处理并查集的时候,对于子节点来说,是满度父节点的集合关系的,所以只要把之前的并查集规则复制一遍,在新处理一下当前节点的就行了。处理过程就是dfs一次树,同时处理并查集 复杂度是
这种算是访问历史版本的并查集应该也算是可持久化并查集了 在每次查询的时候,我们对每个点均处理依次,也只是将跟节点的在一个集合的点放到一个集合.复杂度是
总复杂度就是
附本题代码 #include <bits/stdc++.h>
using namespace std;
#define INF (~(1<<31))
#define INFLL (~(1ll<<63))
#define pb push_back
#define mp make_pair
#define abs(a) ((a)>0?(a):-(a))
#define lalal puts("*******");
#define s1(x) scanf("%d",&x)
#define Rep(a,b,c) for(int a=(b);a<=(c);a++)
#define Per(a,c) for(int a=(b);a>=(c);a--)
#define no puts("NO")
typedef long long int LL ;
typedef unsigned long long int uLL ;
const int N = 100000+7;
const int MOD = 1e9+7;
const double eps = 1e-6;
const double PI = acos(-1.0);
inline int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void fre(){
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
}
/***********************************************************************/
vector<int >T[10005];//树
//vector<pair<int,int > >G;
int G[10005][2];//图
int pre[10005][505];//并查集
int vis[505];//结果
int n,m;
int findi(int x,int y){
int r=x;
while(pre[y][r]!=r) r=pre[y][r];
int i=x,j;
while(i!=j){
j=pre[y][i];
pre[y][i]=r;
i=j;
}
return r;
}
void join(int x,int y,int xy){
int fx=findi(x,xy),fy=findi(y,xy);
if(fx!=fy) pre[xy][fx]=fy;
}
void dfs(int x,int fa){
for(int i=1;i<=n;i++) pre[x][i]=pre[fa][i];
join(G[x][0],G[x][1],x);
int len = T[x].size();
for(int i=0;i<len;i++) dfs(T[x][i],x);
}
int main(){
int _ = 1,kcase;
while(~scanf("%d",&_)){
kcase = 0;
while(_--){
int x,u,v;
scanf("%d%d",&n,&m);
for(int i=0;i<=n;i++)pre[0][i]=i;
for(int i=1;i<=m;i++)T[i].clear();
for(int i=2;i<=m;i++){
scanf("%d",&x);
T[x].pb(i);
}
for(int i=1;i<=m;i++){
scanf("%d%d",&u,&v);
G[i][0]=u,G[i][1]=v;
//G.pb(mp(v,u));
}
dfs(1,0);
//puts("------");
printf("Case #%d:n",++kcase);
int q,k;
scanf("%d",&q);
while(q--){
for(int i=0;i<=n;i++) pre[0][i]=i,vis[i]=0;
scanf("%d",&k);
for(int i=0;i<k;i++){
scanf("%d",&x);
for(int j=1;j<=n;j++){
int ty=findi(j,x);
if(ty!=j) join(j,ty,0);
}
}
int ans=0;
for(int i=1;i<=n;i++){ //计算联通块
int tem=findi(i,0);
if(!vis[tem]) ans++;
vis[tem]=1;
}
printf("%dn",ans);
}
}
}
return 0;
}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |