救救孩子吧,调了一天的题了
查看原帖
救救孩子吧,调了一天的题了
386852
Selvare楼主2021/11/9 18:09

个人思路:

无环:贪心+dfs

有环:

先tarjan求环

dfs到环上时记住入环点较大的那个同在环上的儿子sec

当到某在环上的点u时,若u点只剩一个同在环上的儿子了,且儿子编号还大于sec,就主动回溯。

(其实是题解(by银河奥赛队员 )的思路,但是代码是我自己的)

蒟蒻调了一天了,把所有题解关于回溯或删边的操作都看遍了,但是自己实现的时候总是wa那么一两个点。

#include<bits/stdc++.h>
using namespace std;
/*
sample in:
10 10
10 7
9 4
10 4
10 3
6 10
9 8
3 8
5 8
2 6
10 1

sample out:
1 10 3 4 9 8 5 6 2 7
*/

const int N = 1e+6 + 5;
int n, m;

struct edge
{
	static const int N = 1919810;
	int nxt[N], to[N], head[N], pre[N], val[N], cnt;
	edge(int c = 0)
	{
		this -> cnt = 0;
		memset(head, 0, sizeof(head));
	}
	void add(int x, int y, int w = 0)
	{
		nxt[++cnt] = head[x];
		to[cnt] = y;
		pre[head[x]] = cnt;
		head[x] = cnt;
	}
}ed;

int dfn[N], dfncnt, low[N];
int sz, scc[N], in_scc[N];
int s[N], in_stack[N], tp;

void tarjan(int u, int pre)
{
	int v;
	dfn[u] = low[u] = ++dfncnt;
	s[++tp] = u;
	in_stack[u] = 1;
	for(int i = ed.head[u]; i; i = ed.nxt[i])
	{
		v = ed.to[i];
		if(v == pre) continue;
		if(!dfn[v])
		{
			tarjan(v, u);
			low[u] = min(low[u], low[v]);
		}
		else if(in_stack[v])
			low[u] = min(low[u], dfn[v]);
	}
	if(low[u] == dfn[u])
	{
		int cnt = 0;
		do{
			cnt++;
			if(cnt >= 2) scc[cnt-1] = v, in_scc[v] = 1;
			v = s[tp--];
			in_stack[v] = 0;
		} while(u != v);
		if(cnt >= 2)
		{
			scc[cnt] = v;
			in_scc[v] = 1;
			sz = cnt;
		}
	}
}

bool flag, flag2, flag3;
int sec;
queue<int> q;
bool vis[N];
void DFS(int u)
{
	if(!flag2 && !flag3 && in_scc[u]) flag2 = 1;
	vis[u] = 1;
	q.push(u);
	priority_queue<int, vector<int>, greater<int> > pq;
	for(int i = ed.head[u]; i; i = ed.nxt[i])
	{
		if(flag2 && in_scc[ed.to[i]]) sec = max(sec, ed.to[i]);
		int v = ed.to[i];
		if(!vis[v]) pq.push(v);
	}
	if(flag2) flag2 = 0, flag3 = 1;
	while(!pq.empty())
	{
		int v = pq.top();
		pq.pop();
		if(flag && flag3 && in_scc[v])
			if(pq.empty() && v > sec)
			{
				flag = 0;
				continue;
			}
		if(!vis[v]) DFS(v);
	}
}

int main()
{
	cin >> n >> m;
	if(n == m) flag = 1;
	for(int i = 1, x, y; i <= m; ++i)
	{
		cin >> x >> y;
		ed.add(x, y);
		ed.add(y, x);
	}
	if(flag) tarjan(1, 0);
//	for(int i = 1; i <= sz; ++i)
//		cout << scc[i] <<" ";
//	cout <<endl;
	DFS(1);
	while(!q.empty())
	{
		cout << q.front() <<" ";
		q.pop();
	}
}
2021/11/9 18:09
加载中...