Cow Ski Area G---二维图转一维+tarjan缩点

1.二维转成一维,变成点图

2.tarjan缩点,变成简单DAG,然后就像“校园网校园网--tarjan求缩点的两个经典问题-CSDN博客

变成SCC,即强连通图

3.就像上面说的,特判环,正常情况输出max{in为0的点,ou为0的点}

P1653 [USACO04DEC] Cow Ski Area G - 洛谷

#include<bits/stdc++.h>
using namespace std;
#define N 100011
typedef  long long ll;
int n,m;
int a[505][505];
vector<int> mp[250004];
int low[250004],dfn[250004],sd[250004],cnt,c;
stack<int> st;
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
int ou[250004],in[250004];
void tarjan(int u)
{
	low[u]=dfn[u]=++cnt;
	st.push(u);
	for(int v:mp[u])
	{
		if(!dfn[v])
		{
			tarjan(v);
			low[u]=min(low[u],low[v]);
		}else
		if(!sd[v])
		{
			low[u]=min(low[u],dfn[v]);
		}
	}
	if(dfn[u]==low[u])
	{
		sd[u]=++c;
		while(st.top()!=u)
		{
			sd[st.top()]=c;
			st.pop();
		}
		st.pop();
	}
}
void dfs(int x,int y)
{
	int p1=(x-1)*m+y;
	for(int i=0;i<4;i++)
	{
		int tx=x+dx[i];
		int ty=y+dy[i];
		if(tx>=1&&tx<=n&&ty>=1&&ty<=m)
		{
			if(a[x][y]>=a[tx][ty])
			{
				int p2=(tx-1)*m+ty;
				mp[p1].push_back(p2);
			}
		}
	}
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>m>>n;
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			cin>>a[i][j];
		}
	}
	for(int i=1;i<=n;i++)///二维转一维 
	{
		for(int j=1;j<=m;j++)
		{
			dfs(i,j);
		}
	}
	for(int i=1;i<=n*m;i++)///tarjan缩点 
	{
		if(!dfn[i])
		{
			tarjan(i);
		}
	}
	if(c==1) cout<<0;///是个环 
	else
	{
		for(int i=1;i<=n*m;i++)
		{
			for(int v:mp[i])
			{
				if(sd[i]!=sd[v])
				{
					ou[sd[i]]++;
					in[sd[v]]++;
				}
			}
		}
		int s1=0,s2=0;
		for(int i=1;i<=c;i++)
		{
		if(!ou[i])	s1++;
		if(!in[i])  s2++;
		}
		cout<<max(s1,s2); ///DAG变SCC的经典问题 
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值