枚举,bfs(FZU 2150,Fire Game)

xiaoxiao2021-02-28  124

主要是通过这道题目思考了很多关于树,图的直径,中心等问题。

以下内容跟本题解法弱相关。

说到树的直径(树上最远点对),基本上就是最经典的树形dp了,但是紫书上还介绍了一种很不错的方法,两遍dfs。详见紫书p282。

网上找的详解及证明:http://blog.sina.com.cn/s/blog_dbe928200101cm5t.html

我觉得图应该也是一样的道理。

如果只点一把火的话,只用求下联通快的个数,算出直径,就可以输出答案了。

但是点两把火,求出来的直径就没什么用了,燃烧时间是不能用直径算出来的。

所以只好枚举了。反正数据也小。

图的绝对中心:我记得自己在很久很久以前在cf上做过类似的题目的。

http://blog.csdn.net/crazy_ac/article/details/8816877

代码

#include<stdio.h> #include<algorithm> #include<string.h> #include<queue> using namespace std; const int maxn = 10; const int inf = 0x3f3f3f3f; int n,m; char MAP[maxn][maxn]; int vis[maxn][maxn]; int N; int dr[4]={-1, 0, 1, 0}; int dc[4]={ 0, 1, 0,-1}; bool ok(int r,int c) { return 0<=r&&r<n&&0<=c&&c<m; } int bfs(int S1,int S2) { memset(vis,inf,sizeof(vis)); queue<int>q; q.push(S1); q.push(S2); vis[S1/m][S1%m]=0; vis[S2/m][S2%m]=0; while(!q.empty()) { int now = q.front(); q.pop(); int r = now/m; int c = now%m; for(int i=0;i<4;i++) { int rr = r+dr[i]; int cc = c+dc[i]; if(ok(rr,cc)&&vis[rr][cc]==inf&&MAP[rr][cc]=='#') { vis[rr][cc]=vis[r][c]+1; q.push(rr*m+cc); } } } int ret=0; for(int i=0;i<n;i++) for(int j=0;j<m;j++) if(MAP[i][j]=='#') ret=max(ret,vis[i][j]); return ret; } int solve() { scanf("%d %d",&n,&m); N = n*m; for(int i=0;i<n;i++) scanf("%s",MAP[i]); int ans = inf; for(int i=0;i<N;i++) if(MAP[i/m][i%m]=='#') for(int j=i;j<N;j++) if(MAP[j/m][j%m]=='#') ans=min(ans,bfs(i,j)); if(ans==inf) return 0*puts("-1"); else return 0*printf("%d\n",ans); } int main() { int T; scanf("%d",&T); for(int t=1;t<=T;t++) { printf("Case %d: ",t); solve(); } return 0; }

转载请注明原文地址: https://www.6miu.com/read-40605.html

最新回复(0)