【比赛】NOIP2018 旅行

发现 \(m\) 只有两种取值,于是可做了

树的直接贪心

图的枚举环上的边去掉,然后做树的贪心,搜的时候剪一下枝吧

写得有点乱

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
#define ft first
#define sd second
#define pb(a) push_back(a)
#define mp(a,b) std::make_pair(a,b)
#define REP(a,b,c) for(register int a=(b),a##end=(c);a<=a##end;++a)
#define DEP(a,b,c) for(register int a=(b),a##end=(c);a>=a##end;--a)
const int MAXN=5000+10;
int n,m,e=1,key,beg[MAXN],nex[MAXN<<1],to[MAXN<<1],was[MAXN<<1],cnt,dfn[MAXN],ans[MAXN],vis[MAXN],arv[MAXN];
std::vector<int> V[MAXN];
std::pair<int,int> ext,from[MAXN];
struct Unique{
	int fa[MAXN];
	inline void init(int x)
	{
		REP(i,1,x)fa[i]=i;
	}
	inline int found(int x)
	{
		if(fa[x]!=x)fa[x]=found(fa[x]);
		return fa[x];
	}
	inline int link(int x,int y,int val)
	{
		int u=found(x),v=found(y),res=0;
		if(u!=v)fa[u]=v,res=val;
		return res;
	}
};
Unique U;
template<typename T> inline void read(T &x)
{
	T data=0,w=1;
	char ch=0;
	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
	if(ch=='-')w=-1,ch=getchar();
	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
	x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
	if(x<0)putchar('-'),x=-x;
	if(x>9)write(x/10);
	putchar(x%10+'0');
	if(ch!='\0')putchar(ch);
}
template<typename T> inline bool chkmin(T &x,T y){return y<x?(x=y,true):false;}
template<typename T> inline bool chkmax(T &x,T y){return y>x?(x=y,true):false;}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
inline void insert(int x,int y,int z)
{
	to[++e]=y;
	nex[e]=beg[x];
	beg[x]=e;
	was[e]=z;
}
inline void sortdfs(int x,int f)
{
	if(arv[x])return ;arv[x]=1;
	for(register int i=beg[x];i;i=nex[i])V[x].pb(to[i]),sortdfs(to[i],x);
	std::sort(V[x].begin(),V[x].end());
}
inline void initdfs(int x,int f)
{
	for(register int i=beg[x];i;i=nex[i])
		if(to[i]==f||!was[i])continue;
		else initdfs(to[i],x),from[to[i]]=mp(x,i);
}
inline bool dfs(int x,int f,int &fl)
{
	dfn[++cnt]=x;
	if(dfn[cnt]<ans[cnt])chkmin(fl,0);
	if(fl&&dfn[cnt]>ans[cnt])return false;
	int lack=-1;
	for(register int i=beg[x];i;i=nex[i])
		if(to[i]==f)continue;
		else if(!was[i])lack=to[i];
	REP(i,0,V[x].size()-1)
		if(V[x][i]==lack||V[x][i]==f)continue;
		else if(!dfs(V[x][i],x,fl))return false;
	return true;
}
inline int LCA(int u,int v)
{
	while(u)vis[u]=1,u=from[u].ft;
	while(v)
		if(vis[v])return v;
		else v=from[v].ft;
}
inline void solve(int x)
{
	int fl;
	while(x!=key)
	{
		was[from[x].sd]=was[from[x].sd^1]=0;
		cnt=0;if(dfs(1,0,fl=1))memcpy(ans,dfn,sizeof(ans));
		was[from[x].sd]=was[from[x].sd^1]=1;
		x=from[x].ft;
	}
}
int main()
{
	freopen("travel.in","r",stdin);
	freopen("travel.out","w",stdout);
	read(n);read(m);
	U.init(n);int fl;
	REP(i,1,n)ans[i]=n+1;
	REP(i,1,m)
	{
		int u,v;read(u);read(v);
		if(U.link(u,v,1))insert(u,v,1),insert(v,u,1);
		else ext=mp(u,v);
	}
	if(m==n-1)sortdfs(1,0),dfs(1,0,fl=1),memcpy(ans,dfn,sizeof(ans));
	else
	{
		initdfs(1,0);
		insert(ext.ft,ext.sd,0);
		insert(ext.sd,ext.ft,0);
		sortdfs(1,0);
		dfs(1,0,fl=1),memcpy(ans,dfn,sizeof(ans));
		was[e]=was[e-1]=1;
		key=LCA(ext.ft,ext.sd);
		solve(ext.ft),solve(ext.sd);
	}
	REP(i,1,n)write(ans[i],i==iend?'\n':' ');
	return 0;
}
posted @ 2019-01-01 21:46  HYJ_cnyali  阅读(387)  评论(0编辑  收藏  举报