90pts WA on #2 求调
查看原帖
90pts WA on #2 求调
881015
Resstifnurvˆwˆ.tar.gz楼主2023/8/14 10:39

用的大致是目前题解区第三篇题解的思路

(我拓扑排序排的是边,感觉应该是可行的)

(以及也听从了讨论区其他奆佬的建议,在找的时候把树边的重边跳过了,但是依然没有效果) 贴个代码(马蜂很丑,抱歉orz)

#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;

int n,m;
const int N=1e5+10,M=N;

struct E{
	bool flag;
	int x,y;
	int id;
};
vector<E> e;
bool cmpA(E a,E b){
	return a.flag<b.flag;
}
map<pii,int> id;

int to[M],nt[M],idx,h[N];
inline void add(int x,int y){
	to[idx]=y;
	nt[idx]=h[x];
	h[x]=idx++;
}

const int D=17;

int depth[N];
int zu[N][D+3];

void dfs(int u,int fa){
	depth[u]=depth[fa]+1;
	zu[u][0]=fa;
	
	for(int k=1;k<=D;k++){
		zu[u][k]=zu[zu[u][k-1]][k-1];
	}
	
	for(int i=h[u];i!=-1;i=nt[i]){
		int j=to[i];
		if(j!=fa) dfs(j,u);
	}
}

const int G=2e5+10;
int rk[G];
struct topo_graph{
	int to[G],nt[G],idx,h[G];
	int ru[G];
	inline void init(){
		idx=0;
		memset(h,-1,sizeof(h));
	}
	inline void add(int x,int y){
		to[idx]=y;
		nt[idx]=h[x];
		h[x]=idx++;
		ru[y]++;
	}
	
	int q[G],tt,hh;
	void toposort(){
		tt=-1,hh=0;
		for(int i=0;i<m;i++){
			if(ru[i]==0) q[++tt]=i;
		}
		
		while(hh<=tt){
			int u=q[hh++];
			for(int i=h[u];i!=-1;i=nt[i]){
				int j=to[i];
				ru[j]--;
				if(ru[j]==0) q[++tt]=j;
			}
		}
		
		for(int i=0;i<=tt;i++) rk[q[i]]=i;
	}
} g;

void LCA(int x,int y){ //x先于y的情况 
	for(int k=D;k>=0;k--){
		if(depth[zu[x][k]]>=depth[y]){
			x=zu[x][k];
		}
	}
	
	if(x==y) return ;
	
	for(int k=D;k>=0;k--){
		if(zu[x][k]!=zu[y][k]){
			x=zu[x][k];
			y=zu[y][k];
		}
	}
	
	int lca=zu[x][0];
	pii X=(pii){min(lca,x),max(lca,x)};
	pii Y=(pii){min(lca,y),max(lca,y)};
	g.add(id[X],id[Y]);
}

bool cmp(E a,E b){
	return rk[a.id]<rk[b.id];
}

int main(){
	scanf("%d%d",&n,&m);
	int x,y;
	for(int i=0;i<m;i++){
		scanf("%d%d",&x,&y);
		pii pt=(pii){min(x,y),max(x,y)};
		id[pt]=i;
		e.push_back((E){false,pt.first,pt.second,i});
	}
	
	memset(h,-1,sizeof(h));
	for(int i=1;i<=n;i++){
		scanf("%d",&x);
		if(x!=0){
			pii pt=(pii){min(x,i),max(x,i)};
			e[id[pt]].flag=true;
			add(x,i);
		}
	}
	dfs(1,0);
	
	g.init();
	for(int i=0;i<m;i++){
		if(e[i].flag) continue;
		x=e[i].x,y=e[i].y;
		if(depth[x]==depth[y]) continue;
		else{
			if(depth[x]<depth[y]) swap(x,y);
			x=zu[x][0];
			LCA(x,y);
		}
	}
	g.toposort();
	
	sort(e.begin(),e.end(),cmp);
	for(int i=0;i<m;i++){
		printf("%d %d\n",e[i].x,e[i].y);
	}
	
	return 0;
}

个人感觉卡点可能是我只建了单向边,用pair存边时无脑小的在前,大的在后

(但是我对拍了啊啊啊啊找不出来)
2023/8/14 10:39
加载中...