題目連接:http://poj.org/problem?id=2375
題目大意:一片滑雪場,奶牛隻能向相鄰的而且不高於他當前高度的地方走。想加上纜車是的奶牛能從低的地方走向高的地方,
求最少加的纜車數,是的奶牛能夠從任意一個角落到達任意另外的角落
解題思路:奶牛能夠向相鄰的不高於他的地方走,至關於u,v以前連通。若想加上纜車是圖成爲連通圖,
數目就是max(root, leave);
思路同POJ 1236node
代碼以下:ios
#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][2]; int map[M][M]; int dir[4][2]={{1, 0}, {-1, 0}, {0, 1}, {0, -1}}; 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]=1; for(i=node[u]; i!=-1; 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]=0; belong[j]=cnt_tar; }while(j!=u); } } void solve() { int i; top=0, index=0, cnt_tar=0; memset(dfn, 0, sizeof(dfn)); memset(low, 0, sizeof(low)); for(i=1; 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=0, m=1, n=l*w; memset(node, -1, sizeof(node)); memset(in, 0, sizeof(in)); memset(out, 0, sizeof(out)); for(i=1; i<=w; i++) { for(j=1; j<=l; j++) scanf("%d", &map[i][j]); } for(i=1; i<=w; i++) for(j=1; j<=l; j++) for(ii=0; ii<4; ii++) { int x=i+dir[ii][0], y=j+dir[ii][1]; if(x>=1&&x<=w&&y>=1&&y<=l) { if(map[x][y]<=map[i][j]) { add_Edge((i-1)*l+j, (x-1)*l+y); ee[m][0]=(i-1)*l+j, ee[m++][1]=(x-1)*l+y; } } } solve(); for(i=1; i<=m; i++) { int xx=belong[ee[i][0]], yy=belong[ee[i][1]]; if(xx!=yy) { in[yy]++; out[xx]++; } } int innum=0, outnum=0; for(i=1; i<=cnt_tar; i++) { if(in[i]==0) innum++; if(out[i]==0) outnum++; } if(cnt_tar==1) printf("0\n"); else printf("%d\n", max(innum, outnum)); } return 0; }