首页 > 代码库 > 有向图欧拉路模板

有向图欧拉路模板

纯dfs,但是由于按大部分板子上dfs,会导致某个点已经dfs过一部分边,但在其他层dfs时又会再次访问这些vis过的边,虽然不进行递归,但是仍然需要for循环过去判断vis,因此极限情况仍然比O(n+m)大很多,亲测cf508D上38组样例卡掉,46ms到2s T掉的差距。不过由于某条边访问过之后一定不会再访问,所以可以直接删去那条边,修改head值就行,这样就能做到O(n+m),额……大概吧

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;

const int maxn=1005;		//点数
const int maxm=1005*26;		//边数
int head[maxn],size;
int point[maxm],nxt[maxm],vis[maxm],ind[maxm];
int id[maxn],od[maxn];
int cnt;
int ans[maxm];
void init(){
	cnt=size=0;
	memset(head,-1,sizeof(head));
	memset(vis,0,sizeof(vis));
	memset(id,0,sizeof(id));
	memset(od,0,sizeof(od));
}
void adde(int a,int b,int index){
	point[size]=b;
	ind[size]=index;
	nxt[size]=head[a];
	head[a]=size++;
	od[a]++;id[b]++;
}
void dfs(int s){
	for(int i=head[s];~i;i=nxt[i]){
		if(!vis[i]){
			vis[i]=1;
			dfs(point[i]);
			ans[cnt++]=ind[i];
		}
	}
}
//边数较多的图中可能重复遍历已经访问过的边会T,访问一条边直接删一条边可以更加快速
/*
void dfs(int s){
	while(~head[s]){
		int i=head[s];
		head[s]=nxt[i];
		dfs(point[i]);
		ans[cnt++]=ind[i];
	}
}
*/
void solve(int n,int m){		//n点m边
	int c1=0,c2=0,stx=1;		//stx取标号最小的节点
	for(int i=1;i<=n;i++){
		if(od[i]-id[i]==1)c1++,stx=i;
		else if(od[i]-id[i]==-1)c2++;
		else if(od[i]-id[i]!=0)c1=3;
	}
	if(!((c1==0&&c2==0)||(c1==1&&c2==1))){
		printf("NO\n");
		return;
	}
	dfs(stx);
	if(cnt!=m){
		printf("NO\n");
		return;
	}
	printf("YES\n");
	for(int i=cnt-1;i>=0;--i){
		printf("%d ",ans[i]);
	}
	printf("\n");
}

  

有向图欧拉路模板