第一次写过一个通过人数这么少的题,还没看题解,芜湖!!!
原题链接:https://codeforces.com/contest/1607/problem/F。
大致来说说这道题解题思路。在每个网格块上都有个字母来指引往哪个方向去走,所以我们可以将其转换为图论问题来解决。且每个点都只有一个对外连出的边。那么这个问题就变成了选择起始点,找到当前点能走的最长路径。此时出了一个问题是,构建出的这个图是有环的,且每个点不能经过第二次。经过一番思索我们可以将一个环缩成一个点,只要走到这个点就相当于把环里面的所有点都给走了一遍。那么如何去找环,并获取到环的尺寸?可以先拓扑一下,这样未成环的点都会被过滤掉,剩下的环dfs一遍,能获取到每个环的尺寸。嗯,问题解决了
上代码
#include <bits/stdc++.h>
using namespace std;
char s[2005][2005];
vector<int> nxt,d,in;
vector<bool> used;
int n,m;
void cal(int st,int now,int step){
if(nxt[now]==st){
d[now]=step+1;
return;
}
cal(st,nxt[now],step+1);
d[now]=d[nxt[now]];
}
void topo(){
queue<int>q;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
if(in[(i-1)*m+j]==0) q.push((i-1)*m+j);
while(q.size()){
int now=q.front();q.pop();
if(nxt[now]){
in[nxt[now]]--;
if(in[nxt[now]]==0){
q.push(nxt[now]);
}
}
}
}
void dfs(int x,int y){
int nx=x,ny=y;
if(s[x][y]=='L') ny--;
if(s[x][y]=='R') ny++;
if(s[x][y]=='U') nx--;
if(s[x][y]=='D') nx++;
if(nx<1||nx>n||ny<1||ny>m) return;
nxt[(x-1)*m+y]=(nx-1)*m+ny;
in[(nx-1)*m+ny]++;
}
int get(int now){
if(d[now]) return d[now];
d[now]=1;
//cout<<now<<endl;
if(nxt[now]){
//used[nxt[now]]=1;
d[now]=get(nxt[now])+1;
//used[nxt[now]]=0;
}
return d[now];
}
int main(){
int T;
cin>>T;
while(T--){
in.clear(),nxt.clear(),d.clear();
scanf("%d%d",&n,&m);
in.resize(n*m+5),nxt.resize(n*m+5),d.resize(n*m+5);
for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
dfs(i,j);
}
topo();
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(d[(i-1)*m+j]==0&&in[(i-1)*m+j]) cal((i-1)*m+j,(i-1)*m+j,0);
}
int ans=0,ansx=0,ansy=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
//cout<<d[2]<<endl;
get((i-1)*m+j);
//cout<<d[2]<<endl;
if(d[(i-1)*m+j]>ans){
ans=d[(i-1)*m+j];
ansx=i,ansy=j;
}
}
printf("%d %d %d\n",ansx,ansy,ans);
}
return 0;
}
Comments | NOTHING