你这dfs找回路太假了
查看原帖
你这dfs找回路太假了
184271
l55584楼主2022/8/23 00:31

“假吗?”

“70pts TLE on #8#10#12”

“QWQ”

dfs找回路部分

stack<pair<int,int> > st;//first表示节点,second 表示其在环上的出边 
bool vis[N],ex[N];
void dfs(int t,int s) {
	for(int i=head[t];i;i=head[t])//找一条边(只找一条) 
	{
		head[t]=nxt[i];//保证时间复杂度 
		int to=ver[i];
		if(to==s||vis[i]) continue;//s为上一个节点 ,vis为1表示此边已经删除(被计算过了) 
		st.push(make_pair(t,i));ex[t]=1;//ex为1表示在栈中 ,此处为将当前节点入栈 
		if(ex[to]) //如果目标节点已经在栈中 (找到起点 
		{
			k++;a[k].push_back(to);//加入答案序列(跟题目有关 
			while(st.top().first!=to)//弹出环内所有节点 
			{
				r[st.top().first]-=2;//r是节点的度 
				vis[st.top().second]=1;ex[st.top().first]=0;//删除边,出栈节点 
				a[k].push_back(st.top().first);st.pop();//加入答案序列 
			}
				//对环的起点 进行一样的操作 
			 	r[st.top().first]-=2;
				vis[st.top().second]=1;ex[st.top().first]=0;
				a[k].push_back(st.top().first);st.pop();
			return;
		}
		dfs(to,t);
		return;//只找一条边 
	}
}
int main()
{
	rep(i,1,n) while(r[i])
	{
		dfs(i,0);
		while(!st.empty())//清空栈里剩下的没能被计算的节点(是条链)
		{
			ex[st.top().first]=0;
			st.pop();
		}
	} 
}

也有可能是别的地方出锅了……(但我调了好几个小时了真没看出来)

完整代码

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <string.h>
#include <stack>
#define rep(a,b,c) for(register int a=b;a<=c;++a)
using namespace std;
const int N=1e6+6;
int ver[N<<1],head[N],nxt[N<<1];
int Cnt;
int n,m;
void add(int u,int v) {
	ver[Cnt]=v;
	nxt[Cnt]=head[u];
	head[u]=Cnt;
	Cnt++;
}
inline char gc() {
	static char BB[1000000],*S=BB,*T=BB;
	return S==T&&(T=(S=BB)+fread(BB,1,1000000,stdin),S==T)?EOF:*S++;
}
inline int read() {
	int x=0,f=1;
	char ch=gc();
	while(ch<'0'||ch>'9') {
		if(ch=='-') f=-1;
		ch=gc();
	}
	while(ch<='9'&&ch>='0') {
		x=x*10+ch-48;
		ch=gc();
	}
	return x*f;
}
vector<int> a[N];
int k;
int r[N];
stack<pair<int,int> > st;//first表示节点,second 表示其在环上的出边 
bool vis[N],ex[N];
void dfs(int t,int s) {
	for(int i=head[t];i;i=head[t])//找一条边(只找一条) 
	{
		head[t]=nxt[i];//保证时间复杂度 
		int to=ver[i];
		if(to==s||vis[i]) continue;//s为上一个节点 ,vis为1表示此边已经删除(被计算过了) 
		st.push(make_pair(t,i));ex[t]=1;//ex为1表示在栈中 ,此处为将当前节点入栈 
		if(ex[to]) //如果目标节点已经在栈中 (找到起点 
		{
			k++;a[k].push_back(to);//加入答案序列(跟题目有关 
			while(st.top().first!=to)//弹出环内所有节点 
			{
				r[st.top().first]-=2;//r是节点的度 
				vis[st.top().second]=1;ex[st.top().first]=0;//删除边,出栈节点 
				a[k].push_back(st.top().first);st.pop();//加入答案序列 
			}
				//对环的起点 进行一样的操作 
			 	r[st.top().first]-=2;
				vis[st.top().second]=1;ex[st.top().first]=0;
				a[k].push_back(st.top().first);st.pop();
			return;
		}
		dfs(to,t);
		return;//只找一条边 
	}
}
int main() {
//	freopen("in.in","r",stdin);
	n=read(),m=read();
	int A,B,v;
	rep(i,1,m) {
		A=read();
		B=read();
		v=read()^read();
		if(!v) continue;
		add(A,B);add(B,A);
		r[A]++;r[B]++;
	}
	rep(i,1,n)
	if(r[i]&1) {
		cout<<"NIE\n";
		return 0;
	}
	rep(i,1,n) while(r[i])
	{
		dfs(i,0);
		while(!st.empty())
		{
			ex[st.top().first]=0;
			st.pop();
		}
	} 
	cout<<k<<"\n";
	rep(i,1,k) {
		cout<<a[i].size()-1<<" ";
		rep(j,0,a[i].size()-1) cout<<a[i][j]<<" ";
		cout<<"\n";
	}
	return 0;
}

大佬有更好写法的话请务必分享一下

2022/8/23 00:31
加载中...