2022牛客多校 第9场 C Global Positioning System(讨论+lca+树上差分)

传送门

若干条路径生成了一个无向连通图,只有所有简单回路对应的向量为\(0\)向量时合法。

需要改变的边是满足这个边是所有不为\(0\)回路的交且不属于所有为\(0\)的回路。

因为题目满足一定有合法解,所以若存在不为\(0\)回路,上文所说的所有边都是答案。

若全部回路都为\(0\),所有割边都是答案。

具体的,就是先随便建出一棵生成树,然后对于非树边考虑其与树边构成的简单回路。然后讨论就可以了。

需要注意的是非树边的泰伦,因为满足一定存在合法解,若存在多个不为\(0\)的回路,非树边一定不为答案。若存在一个不为\(0\)回路,这个非树边一定为答案。(这个结论要考虑重合回路和非重合回路的多个回路)。

可以对图\(dfs\)求得生成树,每一条非树边就是返租边可以优化求\(lca\)的过程。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
#define int long long
const int N=5e5+550;
struct edge{
	int to,nxt,x,y,z,id;
}e[N*2];
int cnt,head[N];
void add_edge(int u,int v,int x,int y,int z,int id){
	cnt++;
	e[cnt].nxt=head[u];
	e[cnt].to=v;
	e[cnt].x=x;
	e[cnt].y=y;
	e[cnt].z=z;
	e[cnt].id=id;
	head[u]=cnt;
}
int sum[N][10];
int read(){
	int sum=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
	return sum*f;
}
int f[N][22],dep[N];
void dfs(int u,int F){
	f[u][0]=F;
	dep[u]=dep[F]+1;
	for(int i=1;i<=20;i++)f[u][i]=f[f[u][i-1]][i-1];
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==F)continue;
		sum[v][0]=sum[u][0]+e[i].x;
		sum[v][1]=sum[u][1]+e[i].y;
		sum[v][2]=sum[u][2]+e[i].z;
		dfs(v,u);
	}
}
int get_lca(int x,int y){
	if(dep[x]<dep[y])swap(x,y);
	for(int i=20;i>=0;i--)
		if(dep[f[x][i]]>=dep[y])x=f[x][i];
	if(x==y)return x;
	for(int i=20;i>=0;i--)
		if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
	return f[x][0];
}
struct qu_edge{
	int u,v,x,y,z,id;
}qu_e[N]; 
int num,tmp;
int fa[N];
int find(int x){
	if(x==fa[x])return x;
	else return fa[x]=find(fa[x]);
}
int ans[N];
void get_ans(int u,int f,int type,int id){
	for(int i=head[u];i;i=e[i].nxt){
		int v=e[i].to;
		if(v==f)continue;
		get_ans(v,u,type,e[i].id);
		sum[u][type]+=sum[v][type];
	}
	if(sum[u][type]==tmp&&id)ans[++ans[0]]=id;
} 
signed main(){
	int n=read(),m=read();
	for(int i=1;i<=n;i++)fa[i]=i;
	for(int i=1;i<=m;i++){
		int u=read(),v=read();
		int f_u=find(u),f_v=find(v);
		int x=read(),y=read(),z=read();
		if(f_u==f_v){
			qu_e[++num].x=x;
			qu_e[num].y=y;
			qu_e[num].z=z;
			qu_e[num].u=u;
			qu_e[num].v=v; 
			qu_e[num].id=i;
		} 
		else{
			fa[f_u]=f_v;
			add_edge(u,v,x,y,z,i);
			add_edge(v,u,-x,-y,-z,i);
		}
	}
	dfs(1,0);
	tmp=0;
	int e_id=0;
	for(int i=1;i<=num;i++){
		int u=qu_e[i].u,v=qu_e[i].v;
		int lca=get_lca(u,v);
		sum[u][4]++,sum[v][4]++;
		sum[lca][4]-=2;
		if(sum[u][0]-sum[v][0]==-qu_e[i].x&&sum[u][1]-sum[v][1]==-qu_e[i].y&&sum[u][2]-sum[v][2]==-qu_e[i].z){
			sum[u][3]-=1e9;
			sum[v][3]-=1e9;
			sum[lca][3]+=2e9;
			continue;
		}
		e_id=qu_e[i].id;
		tmp++;
		sum[u][3]++,sum[v][3]++;
		sum[lca][3]-=2;
	}
	if(tmp==1)ans[++ans[0]]=e_id;
	get_ans(1,0,3,0);
	if(ans[0]==0)get_ans(1,0,4,0);
	sort(ans+1,ans+1+ans[0]);
	cout<<ans[0]<<endl;
	for(int i=1;i<=ans[0];i++)cout<<ans[i]<<" "; 
	return 0;
} 
posted @ 2022-08-29 21:08  Xu-daxia  阅读(25)  评论(0编辑  收藏  举报