树上差分

社会主义新天地 提交于 2019-12-02 12:41:50

https://ac.nowcoder.com/acm/contest/1057/C

 #include<bits/stdc++.h> using namespace std; #define MAXN 100005 int T;//最大深度   int n,m; int cnt,first[MAXN<<1],nxt[MAXN<<1]; int u[MAXN<<1],v[MAXN<<1]; void add(int a,int b){     ++cnt;     nxt[cnt]=first[a];first[a]=cnt;     u[cnt]=a,v[cnt]=b; }   int deep[MAXN<<1],f[MAXN][30];   void bfs(int x) {     queue<int> que;     que.push(x);     deep[x]=1;           while(que.size()) {         int cur=que.front();         que.pop();         for(int i=first[cur];i;i=nxt[i]) {             int to=v[i];             if(deep[to])continue;             deep[to]=deep[cur]+1;             f[to][0]=cur;                           for(int j=1;j<=T;j++){                 f[to][j]=f[f[to][j-1]][j-1];             }             que.push(to);         }     } }    inline int lca(int x,int y) {     if(deep[x]>deep[y]) swap(x,y);     for(int i=T;i>=0;i--) {         if(deep[f[y][i]]>=deep[x]) y=f[y][i];     }     if(x==y) return x;     for(int i=T;i>=0;i--) {         if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];     }     return f[x][0]; }   int val[MAXN]; void dfs(int cur,int fa){     for(int i=first[cur];i;i=nxt[i]){         int to=v[i];         if(to==fa)continue;         dfs(to,cur);                   val[cur]+=val[to];     } }     int main(){     scanf("%d%d",&n,&m);     for(int i=1;i<n;i++){         int a,b;         scanf("%d%d",&a,&b);         add(a,b);add(b,a);     }     T=(int)(log(n)/log(2))+1;//最大深度           bfs(1);     for(int i=1;i<=m;i++) {         int a,b;         scanf("%d%d",&a,&b);         val[a]++,val[b]++;         val[lca(a,b)]-=2;     }           dfs(1,0);     int ans=0;     for(int i=2;i<=n;i++){         if(val[i]==0)ans+=m;//随便断一条非树边         if(val[i]==1)++ans;//只有断此条非树边     }     cout<<ans<<endl;           return 0; }

 #include<bits/stdc++.h> using namespace std; #define MAXN 200010  int edgex[MAXN],edgey[MAXN]; int n,m; int cnt,first[MAXN<<1],nxt[MAXN<<1]; int u[MAXN<<1],v[MAXN<<1]; void add(int a,int b){ 	++cnt; 	nxt[cnt]=first[a];first[a]=cnt; 	u[cnt]=a,v[cnt]=b; } vector<int> query[MAXN],query_id[MAXN]; void addQuery(int x,int y,int id){ 	query[x].push_back(y),query_id[x].push_back(id); 	query[y].push_back(x),query_id[y].push_back(id); }  int f[MAXN]; int getf(int x){ 	if(x==f[x])return x; 	return f[x]=getf(f[x]); } void merge(int a,int b){ 	int fa=getf(a),fb=getf(b); 	if(fa!=fb)f[fb]=fa; } int vis[MAXN],deep[MAXN],ans[MAXN]; void tarjan(int cur){ 	vis[cur]=1; 	for(int i=first[cur];i;i=nxt[i]){ 		int to=v[i]; 		if(vis[to])continue; 		deep[to]=deep[cur]+1; 		tarjan(to); 		merge(cur,to); 	} 	for(int i=0;i<query[cur].size();i++){ 		int to=query[cur][i],id=query_id[cur][i]; 		if(vis[to]==2){ 			int lca=getf(to); 			//ans[id]=min(ans[id],deep[cur]+deep[to]-2*deep[lca]);//lca距离  			ans[id]=lca;//lca根结点  		} 	} 	vis[cur]=2; }  int val[MAXN]; void dfs(int cur,int fa){ 	for(int i=first[cur];i;i=nxt[i]){ 		int to=v[i]; 		if(to==fa)continue; 		dfs(to,cur); 		 		val[cur]+=val[to]; 	} }  int main(){ 	scanf("%d%d",&n,&m); 	for(int i=1;i<n;i++){ 		int a,b; 		scanf("%d%d",&a,&b); 		add(a,b);add(b,a); 	} 	for(int i=1;i<=m;i++){ 		int a,b; 		scanf("%d%d",&a,&b); 		if(a==b)ans[i]=b;//不能漏  		addQuery(a,b,i);addQuery(b,a,i); 		edgex[i]=a;edgey[i]=b; 	} 	 	for(int i=1;i<=n;i++)f[i]=i; 	 	tarjan(1); 	 	for(int i=1;i<=m;i++){ 		++val[edgex[i]];++val[edgey[i]]; 		val[ans[i]]-=2; 	} 	 	dfs(1,0); 	int ans=0; 	for(int i=2;i<=n;i++){ 		if(val[i]==0)ans+=m;//随便断一条非树边 		if(val[i]==1)++ans;//只有断此条非树边  	} 	cout<<ans<<endl;  	 	return 0; } 

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!