鉴定为答辩题。
也有可能是我写的答辩了。
思路:对 N 个点每个跑一遍 bfs 求出到其它点的最短路。若是不超过它上面的值 E。则连双向边(并查集维护)
最后判断起点和终点是不是在一起。
一直 WA 4 个点,WA 麻了。
#include<bits/stdc++.h>
// #pragma GCC optimize ("O2")
#define int long long
#define ldb long double
#define For(i,a,b) for(i=a;i<=b;i++)
#define FOR(i,a,b) for(i=a;i>=b;i--)
using namespace std;
const int N=2e2+10;
int n,m;
char a[N][N];
int b[N*N],dis[N*N];
bool vis[N][N];
int dx[4]={0,1,0,-1},dy[4]={1,0,-1,0};
struct node{
int x,y,w;
};
std::vector<int> q;
bool c[N][N];
void bfs(node t){
memset(dis,0x3f,sizeof dis);
memset(vis,0,sizeof vis);
queue<node> Q;
Q.push(t);
dis[(t.x-1)*m+t.y]=0;
while(Q.size()){
auto now=Q.front();
Q.pop();
int i;
if(vis[now.x][now.y]) continue;
vis[now.x][now.y]=1;
For(i,0,3){
int x=now.x+dx[i],y=now.y+dy[i];
if(x<1||x>n||y<1||y>m) continue;
if(a[x][y]=='#') continue;
if(dis[(x-1)*m+y]>now.w+1){
dis[(x-1)*m+y]=now.w+1;
Q.push({x,y,now.w+1});
}
}
}
}
struct DSU{
int fa[N*N],sz[N*N],n;
void init(int n){
int i;
this->n=n;
For(i,1,n) fa[i]=i,sz[i]=1;
}
int find(int x){
if(fa[x]==x) return x;
return fa[x]=find(fa[x]);
}
void merge(int x,int y){
x=find(x),y=find(y);
if(x==y) return ;
if(sz[x]>sz[y]) swap(x,y);
fa[x]=y;
sz[y]+=sz[x];
}
}dsu;
void solve(){
int i,j,cur,now;
For(i,1,n) For(j,1,m) if(a[i][j]=='S') cur=(i-1)*m+j;
else if(a[i][j]=='T') now=(i-1)*m+j;
dsu.init(N*N-1);
For(i,1,n) For(j,1,m) if(c[i][j]){
bfs({i,j,0});
for(auto u:q){
if(u!=(i-1)*m+j){
if(dis[u]<=b[(i-1)*m+j])
dsu.merge((i-1)*m+j,u);
}
}
if(dis[now]<=b[(i-1)*m+j])
dsu.merge((i-1)*m+j,now);
}
if(dsu.find(cur)==dsu.find(now)) cout<<"Yes\n";
else cout<<"No\n";
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
int i,j,t;
// cin>>t;
t=1;
while(t--){
cin>>n>>m;
For(i,1,n) For(j,1,m) cin>>a[i][j];
int Q;
cin>>Q;
For(i,1,Q){
int x,y;
cin>>x>>y;
c[x][y]=1;
q.push_back((x-1)*m+y);
cin>>b[(x-1)*m+y];
}
solve();
}
return 0;
}