【题解】洛谷P1983 车站分级

拓扑排序 不会

那我们可以尝试将指出来的车站与未指出来的车站连边,跑最长路就行了。。。

如果用邻接矩阵的话,是不需要判重的,注意更新数据,跑spfa即可,最后答案应当加上1因为有单独的一级。但会TLE, 只能得70分。

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
using namespace std;
const int maxn=1010;
const int maxm=100020;
int a[maxn][maxn];
bool b[maxn][maxn];
int n,m;
int cnt[maxn];
bool q[maxn];
bool f[maxn];
int team[maxn,dis[maxn];
int s=0,t=0;
int ans=-1e9;
int spfa(int x)
{
	int way=-1e9;
	memset(team,0,sizeof(team));
	memset(f,false,sizeof(f));
	memset(dis,0,sizeof(dis));
	s=0,t=0;
	team[t]=x;
	t++;
	f[x]=true;
	while(s!=t)
	{
		//cout<<s<<' '<<t<<endl;
		int now=team[s];
		//cout<<now<<' '<<dis[now]<<' '<<endl;
		s++;
		s%=n;
		f[now]=false;
		for(int i=1;i<=n;i++)
		{
			if(a[now][i]!=0&&dis[i]<dis[now]+a[now][i])
			{
			//	cout<<now<<' '<<i<<' '<<dis[now]<<' '<<dis[i]<<endl;
				dis[i]=dis[now]+a[now][i];
				if(f[i]==false)
				{
					team[t]=i;
					t++;
					t%=n;
					f[i]=true;
				}
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		way=max(way,dis[i]);
	}
	return way;
}
int main()
{
	//freopen("data.txt","r",stdin);
	cin>>n>>m;
	memset(a,0,sizeof(a));
	for(int i=1;i<=m;i++)
	{
		memset(q,false,sizeof(q));
		int x;
		int w1=0,w2=0; 
		cin>>x;
		for(int qq=1;qq<=x;qq++)
		{
			int w;
			cin>>w;
			if(qq==1) w1=w;
			if(qq==x) w2=w;
			q[w]=true;
		}
		for(int qq=w1;qq<=w2;qq++)
		{
			for(int j=w1;j<=w2;j++)
			{
				if(q[qq]==true&&q[j]==false)
				{
					a[qq][j]=1;
				}
			}
		}
	}
	for(int i=1;i<=n;i++)
	{
		ans=max(ans,spfa(i));
	}
	cout<<ans+1<<endl;
	return 0;
}

那我们需要考虑邻接表,虽然这样能节省空间,但就增加了一个新的判断是否重复建边的问题。判断之后,内存还是会占很多(n*n*m)这个时候,我们就需要设一个虚点(n++),将标记的车站与未标记的车站通过虚点相连,这样就变成(2*n)了,方便许多。注意空间要开的足够大

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdlib>
using namespace std;
const int maxn=1010;
const int maxm=2100000;
int dis[maxm],a[maxn];
bool b[maxn];
int n,m;
int tot,head[maxn*2],nnext[maxm],to[maxm];
void add(int x,int y)
{
	tot++;
	nnext[tot]=head[x];
	head[x]=tot;
	to[tot]=y;
}
int f(int x)
{
	if(dis[x]!=0) return dis[x];
	for(int i=head[x];i;i=nnext[i])
	{
		dis[x]=max(dis[x],f(to[i]));
	}
	dis[x]++;
	return dis[x];
}
int main()
{
	scanf("%d%d",&n,&m);
	int l=n;
	for(int i=1;i<=m;i++)
	{
		int x;
		cin>>x;
		memset(b,false,sizeof(b));
		for(int j=1;j<=x;j++)
		{
			cin>>a[j];
			b[a[j]]=true;
		}
		l++;
		for(int j=a[1];j<=a[x];j++)
		{
			if(b[j]) add(l,j);
		}
		for(int p=a[1];p<=a[x];p++)
		{
			if(!b[p]) add(p,l);
		}
	}
	int ans=0;
	for(int i=1;i<=n;i++)
	{
		ans=max(ans,f(i));
	 } 
	 cout<<(ans+1)/2<<endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/rem_inory/article/details/81162243