题目描述
Farmer John 最近正在修建一个巨大的包含 N×N 个房间的牲口棚,这些房间从(1,1)标号到(N,N)。由于某些原因而害怕黑暗,贝茜这头奶牛想要尽可能地开更多房间的灯。贝茜从房间(1,1)出发,这个房间是唯一一个一开始就亮着的房间。在一些房间中,她会找到一些电灯开关,这些开关她可以用来切换其他房间的灯的状态。比如,在(1,1)这个房间中可能存在一个电灯开关来控制(1,2)房间中的电灯。贝茜只能进电灯开着的房间,并且贝茜只能从房间(x,y)走到四个方向的房间(x-1,y),(x+1,y),(x,y-1)和(x,y+1)(如果在边界的话,那可能会更少)。请帮忙统计贝茜最多可以照亮多少房间。
输入
第一行两个整数 N,M(2<=N<=100,1<=M<=20,000)
下面 M 行,每行用四个整数 x,y,a,b 来表示房间(x,y)存在着可以控制房间(a,b)的灯的开关。一个房间可能有多个开关,一个房间的灯的开关可能存在于多个房间中。
输出
一行一个整数,表示贝茜最多可以照亮的房间数
样例输入
3 6
1 1 1 2
2 1 2 2
1 1 1 3
2 3 3 1
1 3 1 2
1 3 2 1
样例输出
5
提示
在这个样例中,贝茜可以使用房间(1,1)内的开关打开房间(1,2)和(1,3)的灯。然后她可以走到(1,3),使用(1,3)内的开关打开(2,1)的灯,接着可以通过(2,1)打开(2,2)的灯,然而(2,3)是黑暗的,她无法去打开(2,3)房间里的开关,因此,她最多只能打开 5个房间里的灯。
来源/作者: 2017 省中集训
解题思路
BFS
先用邻接表存储开关,每个队列里的房间把能开的灯都开了,再把队列里的点都找一遍,有没有亮的房间扩展
#include<iostream>
#include<cstdio>
using namespace std;
const int way[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
struct DT{
int tox,toy,next;
}a[20200];
int n,m,x1,y1,x2,y2,h,t,num,Gun;
int head[200][200],f[200][200],v[10100][2],light[200][200];
bool check(int x,int y){
return (x>0&&x<=n&&y>0&&y<=n);
}
void bfs(){
f[1][1]=1,h=0,t=1,v[1][0]=1,v[1][1]=1,light[1][1]=1;
while(h++<t){
//**************************************
int z=head[v[h][0]][v[h][1]];
while(z){
light[a[z].tox][a[z].toy]=1;
z=a[z].next;
}
//把灯开了//*****************************
for(int i=1;i<=h;i++)
for(int j=0;j<4;j++){
int xx=v[i][0]+way[j][0],yy=v[i][1]+way[j][1];
if(check(xx,yy)&&!f[xx][yy]&&light[xx][yy]){
v[++t][0]=xx,v[t][1]=yy;
f[xx][yy]=1;
}
}
//找有没有多的可以走的亮着的房间//*********
}
}
int main(){
freopen("light.in","r",stdin);
freopen("light.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
a[++num].tox=x2,a[num].toy=y2,a[num].next=head[x1][y1],head[x1][y1]=num;
}
bfs();
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
Gun+=light[i][j];
printf("%d",Gun);
}