Cpp环境【POJ 2375】【Vijos1642】雪场缆车
2016-07-15 18:14
218 查看
【问题描述】
约翰的表哥罗恩生活在科罗拉多州。他进来打算教他的奶牛们滑雪,但是奶牛们非常害羞,不敢在游人如织的度假胜地滑雪。没办法,他只好自己建滑雪场了。
罗恩的雪场可以划分为W列L行,每个方格都有一个特定的高度H。奶牛可以在相邻邻方格间滑雪,而且不能由低到高滑。
为了保证任意方格可以互通,罗恩打算造一些直达缆车。缆车很强大,可以连接任意两个方格,而且是双向的。而且同一个方格可以造多台缆车。但是缆车的建造费用贵的吓人,所以他希望造尽量少的缆车。那最少需要多少台呢?
【输入格式】
第一行:W和L
接下来是W*H的矩阵地图。
【输出格式】
最小的缆车数
【输入样例】
9 3
1 1 1 2 2 2 1 1 1
1 2 1 2 3 2 1 2 1
1 1 1 2 2 2 1 1 1
【输出样例】
3
【样例解释】
把左下角作为(1,1),建立(3,1) <->(8,2),(7,3)<->(5,2),(1,3)<->(2,2)三部缆车,这样任意两个格子可以互通。
【数据范围】
1<=W<=500;1<=L<=500
0<=H<=9999
【来源】
POJ 2375
【思路梳理】
运用缩点的思想,可以将每一片高度相同的区域可以都看做是一个连通分量,那么在输入图之后对整张图进行处理。因为只能由高度不低于该点的格子移动过来,那么我们可以从高度更高的区域向低的区域连一条有向边。添加缆车就是加一条无向边,使得两个端点所处的区域相互连通。由此观之,我们要向整个图中添加无向边(准确来说应该是双向有向边),使得有向图中所有的连通分量都全部相互强连通。给出cpp代码如下。
【Cpp代码】
#include<queue> #include<cstdio> #include<vector> #include<cstring> #include<iostream> #define maxn 505 using namespace std; int dx[]={-1,1,0,0}; int dy[]={0,0,-1,1}; struct loca { int x,y; }; int w,l,height[maxn][maxn],belong[maxn][maxn],scc=0; int cd[maxn*maxn],rd[maxn*maxn]; vector<int>g[maxn*maxn]; void read(int &x) { x=0;char ch=getchar(); while(ch<'0' || ch>'9') ch=getchar(); while(ch>='0' && ch<='9') { x=x*10+ch-'0'; ch=getchar(); } } loca q[250005];int front,rear; void BFS(int x,int y,int scc) { front=rear=1; q[rear++]=(loca){x,y}; belong[x][y]=scc; while(front!=rear) { x=q[front].x,y=q[front].y;front++; for(int i=0;i<4;i++) { int xx=x+dx[i],yy=y+dy[i]; if(belong[xx][yy] || xx<1 || xx>w || yy<1 || yy>l) continue; if(height[xx][yy]==height[x][y]) { q[rear++]=(loca){xx,yy}; belong[xx][yy]=scc; } } } } int main() { // freopen("in.txt","r",stdin); read(l);read(w); for(int i=1;i<=w;i++) for(int j=1;j<=l;j++) read(height[i][j]); for(int i=1;i<=w;i++) for(int j=1;j<=l;j++)if(!belong[i][j]) BFS(i,j,++scc); for(int i=1;i<=w;i++) for(int j=1;j<=l;j++) for(int k=0;k<4;k++) { int x=i+dx[k],y=j+dy[k]; if(x>w || x<1 || y>l || y<1) continue; if(height[x][y]<height[i][j]) { cd[belong[i][j]]++; rd[belong[x][y]]++; } else if(height[x][y]>height[i][j]) { rd[belong[i][j]]++; cd[belong[x][y]]++; } } int a=0,b=0,ans=0; for(int i=1;i<=scc;i++) { if(rd[i]==0) a++; if(cd[i]==0) b++; } if(scc==1) ans=0; else ans=max(a,b); cout<<ans; return 0; }
相关文章推荐
- C++中const用法总结
- CPP 虚函数、虚函数表及虚拟继承(转)
- Deploying Control Plane Policing
- Thrift的required和optional源码分析
- 初学ACM - 组合数学基础题目PKU 1833
- hdu1827&&hdu2767----Kosaraju算法
- hdu3072&&hdu3639----Kosaraju算法
- POJ ACM 1001
- POJ ACM 1002
- 1611:The Suspects
- POJ1089 区间合并
- POJ 2159 Ancient Cipher
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- POJ-2409-Let it Bead&&NYOJ-280-LK的项链
- POJ-1695-Magazine Delivery-dp
- POJ1523 SPF dfs
- POJ-1001 求高精度幂-大数乘法系列