codeforces1103C Johnny Solving

https://codeforces.com/problemset/problem/1103/C

亂搞了一下午,TLE on 30,換一種方式 TLE on 35。。。

然後看了題解,看了一半,自己想,又wa了好久,最後還是把最後給看了。。。。

假設有c個葉子節點,設dep[1]=1,那麼對於這c個葉子節點(dep[i1]+dep[i2]+...dep[ic])>=n,因爲每個點都會被至少一條路徑覆蓋到,然後根節點1可能會被覆蓋到多次。那麼max{dep[i1],dep[i2]...dep[ic]}>=n/c,所以dfs樹的葉子節點個數和深度是有關係的 。

所以以1位根節點建dfs樹,如果深度>=n/k,直接記路徑,不超過n/k,那麼至少就會有k個葉子節點,對於每個葉子節點除了連向父親的邊,至少還有向上的兩條邊,所以會得到3個環,且至少有一個環的長度>3,設葉子節點爲u,這兩條邊向上到的點爲d1,d2,假設(dep[u]-dep[d1]+1)%3==0,(dep[u]-dep[d1]+1)%3==0,這兩個圓就是不行的,但是從這兩個式子我們發現dep[d1]%3==dep[d2]%3,那麼對於d1...d2.u這個環的長度爲(dep[d1]-dep[d2]+2)一定=2。所以這3個環必有一個符合條件。

由於無向圖dfs樹葉子節點互相沒有到達,所以以每個葉子節點爲第一個點就好了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxl=5e5+10;

int n,m,ans,cas,k,tot,cnt,up;
bool flag;
int a[maxl],du[maxl],dep[maxl],fa[maxl],leaf[maxl];
vector<int> e[maxl];
bool vis[maxl];
vector<int> b[maxl];

inline void dfs(int len,int u)
{
	vis[u]=true;a[len]=u;bool son=false;
	if(len==up)
	{
		ans=1;
		for(int i=1;i<=len;i++)
			b[1].push_back(a[i]);
		return;
	}
	for(int v:e[u])
	{
		if(vis[v] || v==fa[u])continue;
		dep[v]=dep[u]+1;fa[v]=u;son=true;
		dfs(len+1,v);
		if(ans)
			return;
	}
	if(!son)
		leaf[++tot]=u;
	a[len]=0;
}

inline void prework()
{
	scanf("%d%d%d",&n,&m,&k);
	int u,v;up=n/k+(n%k!=0);
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&u,&v);
		e[u].push_back(v);du[u]++;
		e[v].push_back(u);du[v]++;
	}
	ans=0;dep[1]=1;fa[1]=0;
	dfs(1,1);
} 

inline void mainwork()
{
	if(ans)
		return;
	ans=2;int d1,d2,u,d;
	for(int i=1;i<=k;i++)
	{
		d1=0;d2=0;u=leaf[i];
		for(int v:e[u])
		if(v!=fa[u])
		{
			if(!d1) d1=v;
			else{d2=v;break;}
		}
		if(dep[d1]<dep[d2])
			swap(d1,d2);
		if(dep[u]-dep[d1]+1>=3 && (dep[u]-dep[d1]+1)%3!=0)
		{
			d=u;
			while(d!=d1)
			{
				b[i].push_back(d);
				d=fa[d];
			}
			b[i].push_back(d1);
		}
		else if(dep[u]-dep[d2]+1>=3 && (dep[u]-dep[d2]+1)%3!=0)
		{
			d=u;
			while(d!=d2)
			{
				b[i].push_back(d);
				d=fa[d];
			}
			b[i].push_back(d2);
		}
		else
		{
			b[i].push_back(u);d=d1;
			while(d!=d2)
			{
				b[i].push_back(d);
				d=fa[d];
			}
			b[i].push_back(d2);
		}
	}
}

inline void print()
{
	if(!ans)
		puts("-1");
	else if(ans==1)
	{
		puts("PATH");
		printf("%d\n",up);
		for(int i=0;i<up;i++)
			printf("%d%c",b[1][i],(i==up-1)?'\n':' ');
	}
	else
	{
		puts("CYCLES");int l;
		for(int i=1;i<=k;i++)
		{
			l=b[i].size();
			printf("%d\n",l);
			for(int j=0;j<l;j++)
				printf("%d%c",b[i][j],(j==l-1)?'\n':' ');
		}
	}
}

int main()
{
	int t=1;
	//scanf("%d",&t);
	for(cas=1;cas<=t;cas++)
	{
		prework();
		mainwork();
		print();
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章