一、基础
图的存储方式
邻接矩阵
多条边 邻接表
有向边 邻接矩阵不对称
二、dfs遍历结点
每次选择一个一个没有访问过的结点然后dfs,直到每一个点都被访问
非递归:用栈,可以用STL写
三、bfs
分层,
1、访问顶点v
2、访问与顶点v距离k且没有被访问过的顶点
3、如果搞完了还有顶点没访问,从任一个没访过的点开始重新bfs
用队列(STL)实现,一个数指头一个指尾,每次从头取一个点,然后遍历它的下一级点,加到tail后面,终止:head=tail
例题:
1、flood-fill问题 - 数陆地块11994
每次都找到一个没遍历过的点,对它上下左右遍历,直到把它周围的路地块全部遍历一遍,每次找到这样的点可以cnt++
#include<iostream>
using namespace std;
int n,m,ans = 0;
int a[505][505] = {0};
bool vis[505][505] = {0};
int dx[4] = {1,0,-1,0},dy[4] = {0,1,0,-1};
void dfs(int x,int y){
for(int i=0;i<4;i++){
if(x+dx[i]>n||x+dx[i]<1||y+dy[i]>m||y+dy[i]<1) continue;
if(vis[x+dx[i]][y+dy[i]]==0 && a[x+dx[i]][y+dy[i]]==0) {
vis[x+dx[i]][y+dy[i]] = true;
dfs(x+dx[i],y+dy[i]);
}
}
return ;
}
int main(){
cin>>n>>m;
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++){
if(vis[i][j]==0 && a[i][j]==0) {
vis[i][j] = true;
dfs(i,j);
ans ++;
}
}
cout<<ans<<endl;
return 0;
}
2、寻路问题:方格上二人都到同一个点14175
选择酒吧:可以选的每一个点都作为目标点来一次,ans取min
本来是最短路问题,但是每走一条边代价相同,所以可以用bfs实现
#include<iostream>
using namespace std;
const int N = 1005;
struct Node{
int x,y;
int dist;
};
Node a[N*N],a1[N*N],a2[N*N],h,s;
char c[N][N];
int n,m,barr = 0,head,tail,tail1,ans1,ans2,ans = 2*N*N;
Node bar[N*N];
int dx[4] = {1,0,-1,0},dy[4] = {0,1,0,-1};
bool vis[N][N];
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
cin>>c[i][j];
if(c[i][j]=='#') continue;
if(c[i][j]=='B') {
bar[++barr].x = i;
bar[barr].y = j;
}
if(c[i][j]=='H') {
h.x = i;
h.y = j;
}
if(c[i][j]=='S') {
s.x = i;
s.y = j;
}
}
for(int i=0;i<=m+1;i++) c[0][i] = c[n+1][i] = '#';
for(int i=0;i<=n+1;i++) c[i][0] = c[i][m+1] = '#';
// for(int i=0;i<=n+1;i++) {
// for(int j=0;j<=m+1;j++) cout<<c[i][j]<<" ";
// cout<<endl;
// }
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
vis[i][j] = false;
head = 0;tail = 1;
a1[0].x = h.x ;
a1[0].y = h.y ;
a1[0].dist = 0;
vis[h.x][h.y] = true;
while(head!=tail){
Node u;
u.x = a1[head].x ;
u.y = a1[head].y ;
u.dist = a1[head].dist ;
for(int i=0;i<4;i++){
if(c[u.x+dx[i]][u.y+dy[i]]!='#' && vis[u.x+dx[i]][u.y+dy[i]]==0) {
a1[tail].x = u.x+dx[i];
a1[tail].y = u.y+dy[i];
a1[tail].dist = u.dist +1;
vis[u.x+dx[i]][u.y+dy[i]] = true;
tail++;
}
}
head++;
}
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
vis[i][j] = false;
tail1 = tail;
head = 0; tail = 1;
a2[0].x = s.x ;
a2[0].y = s.y ;
a2[0].dist = 0;
vis[s.x][s.y] = true;
while(head!=tail){
Node u;
u.x = a2[head].x ;
u.y = a2[head].y ;
u.dist = a2[head].dist ;
for(int i=0;i<4;i++){
if(c[u.x+dx[i]][u.y+dy[i]]!='#' && vis[u.x+dx[i]][u.y+dy[i]]==0) {
a2[tail].x = u.x+dx[i];
a2[tail].y = u.y+dy[i];
a2[tail].dist = u.dist +1;
vis[u.x+dx[i]][u.y+dy[i]] = true;
tail++;
}
}
head++;
}
for(int i=1;i<=barr;i++){
ans1 = N*N;
ans2 = N*N;
for(int j=0;j<=tail1;j++){
if(bar[i].x == a1[j].x && bar[i].y == a1[j].y ) {
ans1 = a1[j].dist ;
break;
}
}
if(ans1==N*N) continue;
for(int j=0;j<=tail;j++){
if(bar[i].x == a2[j].x && bar[i].y == a2[j].y ) {
ans2 = a2[j].dist ;
break;
}
}
if(ans>ans1+ans2) ans = ans1 + ans2;
// cout<<ans1<<" "<<ans2<<endl;
}
cout<<ans<<endl;
return 0;
}
改了好久!!首先T掉是因为对每个B都搜了两次,铁定超时;第二是没加检验ans1的一步,T了一个点,加上后过了。写了struct的node,美观很多,很多东西都用node类型,好写很多!