列表

详情


NC231372. Dynamic Graph

描述

There is an undirected graph with n vertices and no edges initially.

Let's define the weight of the path consisting of k edges with indices as .

Notice that a path may not be simple. That is, it can go through the same vertices or the same edges multiple times, and the weight will also be the sum for multiple times if so.

You need to perform m operations.

There are 3 types of operations:

: add an edge between u and v with weight w

: delete the edge added in the id-th operation.

: If there is a path between u and v with weight , print 1. Otherwise, print 0. Notice that a path may not be simple.

给定一个 n 个点的无向图,一开始没有边。

对于一条有 k 条边,且边的编号依次为  的路径,其的长度为 .

注意一条路径不必是简单路径。也就是说,它可以多次经过同一个点或同一条边,在这种情况下计算路径的长度时也会将边的长度累加多次。

你需要执行 m 次操作。

操作有 3 种:

: 在 u 和 v 之间加了一条长 w 的边。

: 删除第 id 次操作添加的边。

: 询问是否存在一条模 F 余 w 的从 u 到 v 的路径(可以不是简单路径)。如果有,输出 1。否则,输出 0

输入描述

The first line contains 3 integers  --- the numbers of vertices of the graph, the number of operations in the graph, and the modulo.

Then m lines follow. The i-th line contains the i-th operation. The format of the operation input is shown above. 

In operations, all tokens are non-negative integers. .

It's guaranteed that in each operation 2, the id must be an operation of type 1 and it has not been deleted by another operation 2.

第一行有 3 个整数,  。

接下来有 m 行,每行描述一个操作。

操作格式同题目描述。

题目保证,所有输入的数均为非负整数,且 .

题目保证执行第 2 种操作时, id 对应的操作为第 1 种,且还未被删。

输出描述

For each operation of types 1, output a line containing the answer.

对于每个询问操作,输出一行一个整数表示答案。

示例1

输入:

10 19 96
1 3 1 48
1 3 2 16
2 2
2 1
1 3 3 24
1 2 2 16
1 2 3 6
1 2 3 48
1 2 2 48
1 1 3 16
1 3 3 48
2 5
3 3 4 16
3 3 3 8
1 2 1 48
2 6
3 3 1 32
2 7
2 8

输出:

0
1
1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 179ms, 内存消耗: 25976K, 提交时间: 2021-12-28 20:01:02

#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
const int MAXN=1e5+5,MAXS=2e7;
int gcd(int a,int b){
	if(!b) return a;
	return gcd(b,a%b);
}
int n,m,F,op[MAXN][4],edt[MAXN],ans[MAXN];
struct Edge{
	int u,v,w;
};
vector<Edge> ed[MAXN<<2];
#define lc k<<1
#define rc k<<1|1
#define ls lc,l,mid
#define rs rc,mid+1,r
void Modify(int k,int l,int r,int x,int y){
	if(x<=l&&r<=y){
		ed[k].push_back((Edge){op[x][1],op[x][2],op[x][3]});
		return ;
	}
	int mid=l+r>>1;
	if(x<=mid) Modify(ls,x,y);
	if(mid<y) Modify(rs,x,y);
	return ;
}
struct Change{
	int *w,v;
}stk[MAXS];
int top;
inline void c(int &x,int y){
	if(x!=y){
		stk[++top]=(Change){&x,x};
		x=y;
	}
}
int pre[MAXN],gs[MAXN],siz[MAXN],fw[MAXN],sum[MAXN];
int fnd(int x){
	if(x==pre[x]) return sum[x]=0,x;
	int res=fnd(pre[x]);
	sum[x]=sum[pre[x]]^fw[x];
	return res;
}
void Query(int k,int l,int r){
	int tp=top;
	for(Edge e:ed[k]){
		int u=e.u,v=e.v;
		int x=fnd(u),y=fnd(v);
		if(x==y){
			int g=gcd(gs[x],e.w*2);
			if(__builtin_ctz(sum[u]^sum[v]^e.w)<__builtin_ctz(g)) g>>=1;
			c(gs[x],g);
		}else{
			//printf("Merge %d %d\n",x,y);
			if(siz[x]>siz[y]) swap(x,y);
			fw[x]=sum[u]^sum[v]^e.w;
			c(pre[x],y);
			c(siz[y],siz[x]+siz[y]);
			c(gs[y],gcd(gcd(gs[x],gs[y]),e.w*2));
		}
	}
	if(l==r){
		if(op[l][0]==3){
			//puts("op3");
			int u=op[l][1],v=op[l][2],w=op[l][3];
			int x=fnd(u),y=fnd(v);
			//printf("x %d y %d\n",x,y);
			if(x==y){
				int g=gs[x];
				if(__builtin_ctz(sum[u]^sum[v])<__builtin_ctz(g)) ans[l]=(w%g==g/2);
				else ans[l]=(w%g==0);
			}
		}
	}else{
		int mid=l+r>>1;
		Query(ls);
		Query(rs);
	}
	while(top>tp){
		*stk[top].w=stk[top].v;
		top--;
	}
	return ;
}
int main(){
	//freopen("rand","r",stdin);
	scanf("%d%d%d",&n,&m,&F);
	for(int i=1; i<=m; i++){
		scanf("%d%d",op[i],op[i]+1);
		if(op[i][0]!=2) scanf("%d%d",op[i]+2,op[i]+3);
		else edt[op[i][1]]=i;
	}
	for(int i=1; i<=m; i++)
		if(op[i][0]==1) Modify(1,1,m,i,edt[i]?edt[i]:m);
	for(int i=1; i<=n; i++)
		pre[i]=i,siz[i]=1,gs[i]=F;
	Query(1,1,m);
	for(int i=1; i<=m; i++)
		if(op[i][0]==3) printf("%d\n",ans[i]);
	return 0;
}

上一题