POJ2375 Cow Ski Area

題意:給出一張地圖,一隻牛可以從高度大的地方走到高處小的地方,高度相同的地方隨便走,問最少連接幾個塊,可以使牛從任何一個點走到任何一個點。。

強連通,建圖很簡單,就是同樣高度建個雙相邊,有高度差是單向邊(高度大到高度小),然後tarjan縮點,然後統計縮點之後每個點的入度和出度,統計出度爲0和入度爲0的點,取這兩個中的最大值。。。如果強連通分量只有一個,整張圖都是連通的,輸出0。。

然後就是RE了。。。。discuss裏說交C++,交了C++。。居然TLE。。。然後就鬱悶了。。。最後把vector換成鄰接表就過了900+ms...

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;
const int MAXN=510;
const int dir[4][2]={1,0,-1,0,0,1,0,-1};
int mp[MAXN][MAXN];
int n,m;
int sc_cnt,dfs_clock,sccno[MAXN*MAXN],pre[MAXN*MAXN],low[MAXN*MAXN];
stack<int> S;
struct EDGE
{
	int v,next;
}edge[MAXN*MAXN*8];
int head[MAXN*MAXN],size;
void init()
{
	memset(head,-1,sizeof(head));
	memset(sccno,0,sizeof(sccno));
	memset(pre,0,sizeof(pre));
	sc_cnt=dfs_clock=size=0;
}
void add_edge(int u,int v)
{
	edge[size].v=v;
	edge[size].next=head[u];
	head[u]=size++;
}
void tarjan(int u)
{
	low[u]=pre[u]=++dfs_clock;
	S.push(u);
	for(int i=head[u];i!=-1;i=edge[i].next)
	{
		int v=edge[i].v;
		if(!pre[v])
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}
		else if(!sccno[v])
		{
			low[u]=min(low[u],pre[v]);
		}
	}
	if(low[u]==pre[u])
	{
		sc_cnt++;
		while(1)
		{
			int x=S.top();
			S.pop();
			sccno[x]=sc_cnt;
			if(x==u)
				break;
		}
	}
}
int in[MAXN*MAXN],out[MAXN*MAXN];
int solve()
{
	int i,j,k;
	int u,v;
	for(i=0;i<n;i++)
	{
		for(j=0;j<m;j++)
		{
			for(k=0;k<4;k++)
			{
				int nx=i+dir[k][0];
				int ny=j+dir[k][1];
				if(nx<0||ny<0||nx>=n||ny>=m)
					continue;
				u=i*m+j;
				v=nx*m+ny;
				if(mp[i][j]>=mp[nx][ny])
				{
					add_edge(u,v);
				}
				if(mp[i][j]<=mp[nx][ny])
				{
					add_edge(v,u);
				}
			}
		}
	}
	for(i=0;i<n*m;i++)
	{
		if(!pre[i])
			tarjan(i);
	}
	if(sc_cnt==1)
	{
		return 0;
	}
	memset(in,0,sizeof(in));
	memset(out,0,sizeof(out));
	for(u=0;u<n*m;u++)
	{
		for(i=head[u];i!=-1;i=edge[i].next)
		{
			int v=edge[i].v;
			if(sccno[u]!=sccno[v])
			{
				out[sccno[u]]++;
				in[sccno[v]]++;
			}
		}
	}
	int a=0,b=0;
	for(i=1;i<=sc_cnt;i++)
	{
		if(!in[i])
			a++;
		if(!out[i])
			b++;
	}
	return max(a,b);
}
int main()
{
	int i,j;
	while(scanf("%d%d",&m,&n)==2)
	{
		init();
		for(i=0;i<n;i++)
		{
			for(j=0;j<m;j++)
			{
				scanf("%d",&mp[i][j]);
			}
		}
		printf("%d\n",solve());
	}
}


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