有向图欧拉路模板

纯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");
}

  

时间: 2024-11-13 06:34:04

有向图欧拉路模板的相关文章

poj 1386 Play on Words(有向图欧拉路+并查集)

题目链接:http://poj.org/problem?id=1386 思路分析:该问题要求判断单词是否能连接成一条直线,转换为图论问题:将单词的首字母和尾字母看做一个点,每个单词描述了一条从首字母指向尾字母的有向边, 则则所有的单词构成了一个有向图,问题变为判断该有向图中是否存在一条欧拉路:有向图中存在欧拉路的两个充分必要条件为:该图是联通的并且所有的点的入度等于出度或者只存在两个点的入度与出度不等,一个点的入度=出度+1,另一个点的入度=出度-1: 代码如下: #include <cstdi

POJ1386Play on Words[有向图欧拉路]

Play on Words Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 11846   Accepted: 4050 Description Some of the secret doors contain a very interesting word puzzle. The team of archaeologists has to solve it to open that doors. Because ther

POJ 2337 &amp;&amp; ZOJ 1919--Catenyms 【有向图 &amp;&amp; 欧拉路判断 &amp;&amp; 欧拉路径】

Catenyms Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 10427   Accepted: 2726 Description A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For

CCF 送货 + 欧拉路模板

#include <bits/stdc++.h> using namespace std; stack<int> st; vector<int> vec[10005]; bool mp[10005][10005]; int vis[10005],cp[10005]; int n,m; void pd(int a)//先判断是不是联通图 { cp[a]=1; vector<int>::iterator it; for(it=vec[a].begin();it!

欧拉路&amp;&amp;欧拉回路 概念及其练习

欧拉路: 如果给定无孤立结点图G,若存在一条路,经过图中每边一次且仅一次,这条路称为欧拉路: 如果给定无孤立结点图G,若存在一条回路,经过图中每边一次且仅一次,那么该回路称为欧拉回路. 存在欧拉回路的图,称为欧拉图. 一. 对于无向图G,具有一条欧拉路,当且仅当G是连通的,且有零个或两个奇数度结点. 且有零个奇数度结点,存在欧拉回路:有两个奇数度结点,存在欧拉路. 判断无向图G是否连通,可以从任意结点出发,进行深度优先遍历,如果可以遍历到所有点,也可以用并查集,判断根节点的个数, 说明,图G连通

Play on Words UVA 10129 (有向图的欧拉路)

说说: 这道题的题意很简单,就是给你一些单词,问是否能形成一个句子,使前一个单词的最后一个字母等于后一个单词的第一个字母.本质上来说就是有向图的欧拉路问题,当然存在欧拉回路也是OK的.一开始的时候,我以为存在欧拉路只需判断两种情况:一,是存在欧拉回路,即每个节点的入度等于出度.二,存在欧拉路,有且仅有一个节点的入度比出度大一,一个节点的出度比入度大一.只要满足任意其中一种情况即可.事实上不是这样的,其实还需要判断该图是否连通.这自然而然就想到了并查集的思想.当出现两个节点的时候,将其中的一个节点

欧拉路

欧拉路径和欧拉回路欧拉路径:从某结点出发一笔画成所经过的路线叫做欧拉路径.欧拉回路:在欧拉路径的基础上又回到起点.a.凡是由偶点组成的连通图,一定可以一笔画成.画时可以把任一偶点为起点,最后一定能以这个点为 终点画完此图. b.凡是只有两个奇点的连通图(其余都为偶点),一定可以一笔画成.画时必须把一个奇点为起点,另 一个奇点终点. c.其他情况的图都不能一笔画出.(有偶数个奇点除以2便可算出此图需几笔画成.) 欧拉回路和欧拉路径的判断欧拉回路:无向图:每个顶点的度数都是偶数,则存在欧拉回路.有向

欧拉路HDU3018

欧拉路,欧拉回路,讲的实际上就是一笔画的问题. 给定n个点,m条边,如果能一笔把所有边都连上就是欧拉路,如果起点和终点是同一点,就是欧拉回路. 欧拉路的特征:对于无向图,如果所有点的度都是偶数,那么任意点都可以作为欧拉路的起点:如果存在两个点的度是奇数,其他点的度都是偶数,那么这两个分别作为欧拉路的起点和终点. 对于有向图,如果每个点的入度和出度相同,一定能形成欧拉路:如果存在两个点的入度和出度是奇数,以这两个点为起点和终点可以形成一条欧拉路.4 判断给定一个连通图通过几笔能画出来:一笔画能消去

POJ 2337 欧拉路

Catenyms Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11214   Accepted: 2908 Description A catenym is a pair of words separated by a period such that the last letter of the first word is the same as the last letter of the second. For