题目链接:http://poj.org/problem?id=2375
题目大意:一片滑雪场,奶牛只能向相邻的并且不高于他当前高度的地方走。想加上缆车是的奶牛能从低的地方走向高的地方,
求最少加的缆车数,是的奶牛可以从任意一个角落到达任意另外的角落
解题思路:奶牛可以向相邻的不高于他的地方走,相当于u,v之前连通。若想加上缆车是图成为连通图,
数目就是max(root, leave);
思路同POJ 1236
代码如下:
#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
#define M 505
#define N 2000005
struct Edge
{
int v, next;
}edge[N]; int node[N], stack[N], instack[N], dfn[N], out[N], in[N];
int low[N], belong[N], index, cnt_edge, n, m, cnt_tar, top;
int ee[N][];
int map[M][M];
int dir[][]={{, }, {-, }, {, }, {, -}}; void add_Edge(int u, int v)
{
edge[cnt_edge].next=node[u];
edge[cnt_edge].v=v;
node[u]=cnt_edge++;
}
void tarjan(int u)
{
int i, j, v;
dfn[u]=low[u]=++index;
stack[++top]=u;
instack[u]=;
for(i=node[u]; i!=-; i=edge[i].next)
{
v=edge[i].v;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u], low[v]);
}
else if(instack[v])
low[u]=min(low[u], dfn[v]);
}
if(dfn[u]==low[u])
{
cnt_tar++;
do
{
j=stack[top--];
instack[j]=;
belong[j]=cnt_tar;
}while(j!=u);
}
}
void solve()
{
int i;
top=, index=, cnt_tar=;
memset(dfn, , sizeof(dfn));
memset(low, , sizeof(low));
for(i=; i<=n; i++)
if(!dfn[i])
tarjan(i);
}
int main()
{
int i, ii, w, l, j, x, y;
while(scanf("%d%d", &l, &w)!=EOF)
{
cnt_edge=, m=, n=l*w;
memset(node, -, sizeof(node));
memset(in, , sizeof(in));
memset(out, , sizeof(out));
for(i=; i<=w; i++)
{
for(j=; j<=l; j++)
scanf("%d", &map[i][j]);
}
for(i=; i<=w; i++)
for(j=; j<=l; j++)
for(ii=; ii<; ii++)
{
int x=i+dir[ii][], y=j+dir[ii][];
if(x>=&&x<=w&&y>=&&y<=l)
{
if(map[x][y]<=map[i][j])
{
add_Edge((i-)*l+j, (x-)*l+y);
ee[m][]=(i-)*l+j, ee[m++][]=(x-)*l+y;
}
}
}
solve();
for(i=; i<=m; i++)
{
int xx=belong[ee[i][]], yy=belong[ee[i][]];
if(xx!=yy)
{
in[yy]++;
out[xx]++;
}
}
int innum=, outnum=;
for(i=; i<=cnt_tar; i++)
{
if(in[i]==)
innum++;
if(out[i]==)
outnum++;
}
if(cnt_tar==)
printf("0\n");
else
printf("%d\n", max(innum, outnum));
}
return ;
}