http://acm.timus.ru/problem.aspx?space=1&num=1699
从一个点到另一个点正好有一条路 所以原图是一棵树
先求出每一对点的最近公共祖先lca
然后一遍dfs 求出每个点到它的lca的转弯数 最后还要判定两个点在lca处是否还要一个转弯
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<map> #include<vector> #include<stack> #include<set> #include<map> #include<queue> #include<deque> #include<algorithm> #include<cmath> #define LL long long #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; const int INF=0x3f3f3f3f; const int N=100005; int head[N],I; struct node { int j,next; int k; }edge[N*10]; int X[]={0,0,-1,1}; int Y[]={-1,1,0,0}; int K[]={1,1,2,2}; char grap[N]; bool visited[N]; int q1[N],q2[N],lca[N],d[N],prek[N],tok[N],k1[N],k2[N],ans[N]; int f[N]; vector<int>vt[N]; queue<int>qt; int n,m; void add(int i,int j,int k) { edge[I].j=j; edge[I].k=k; edge[I].next=head[i]; head[i]=I++; } void bfs(int s) { memset(visited,false,sizeof(visited)); visited[s]=true; qt.push(s); while(!qt.empty()) { int x=qt.front(); qt.pop(); for(int i=0;i<4;++i) { int l1=x/m+X[i]; int l2=x%m+Y[i]; int st=x,nd=l1*m+l2; while(l1>=0&&l1<n&&l2>=0&&l2<m&&grap[nd]=='#'&&!visited[nd]) { visited[nd]=true; qt.push(nd); add(st,nd,K[i]); st=nd; l1=l1+X[i]; l2=l2+Y[i]; nd=l1*m+l2; } } } } int fx(int x) { if(f[x]!=x) f[x]=fx(f[x]); return f[x]; } void findLca(int x) { for(unsigned int i=0;i<vt[x].size();++i) { int l=vt[x][i]; if(q1[l]==x) { if(f[q2[l]]!=-1) lca[l]=fx(q2[l]); }else { if(f[q1[l]]!=-1) lca[l]=fx(q1[l]); } } } void dfsLca(int x,int pre) { f[x]=x; findLca(x); for(int t=head[x];t!=-1;t=edge[t].next) { int j=edge[t].j; dfsLca(j,x); } f[x]=pre; } void F(int x) { for(unsigned int i=0;i<vt[x].size();++i) { int l=vt[x][i]; int y=lca[l]; if(x==q1[l]) k1[l]=tok[y]; else k2[l]=tok[y]; ans[l]+=(d[x]-d[y]); if((prek[y]&tok[y])==0) --ans[l]; } } void dfs(int x,int dt,int kt) { d[x]=dt; prek[x]=kt; tok[x]=3; F(x); for(int t=head[x];t!=-1;t=edge[t].next) { int j=edge[t].j; tok[x]=edge[t].k; if((prek[x]&tok[x])==0) dfs(j,dt+1,edge[t].k); else dfs(j,dt,edge[t].k); } } int main() { //freopen("data.in","r",stdin); cin>>n>>m; int s=-1; for(int i=0;i<n;++i) for(int j=0;j<m;++j) { cin>>grap[i*m+j]; if(s==-1&&grap[i*m+j]=='#') s=i*m+j; } memset(head,-1,sizeof(head)); I=0; bfs(s); int q; cin>>q; for(int i=0;i<q;++i) { int x1,y1,x2,y2; cin>>x1>>y1>>x2>>y2; --x1;--y1;--x2;--y2; q1[i]=x1*m+y1; q2[i]=x2*m+y2; if(q1[i]!=q2[i]) vt[q1[i]].push_back(i); vt[q2[i]].push_back(i); } memset(f,-1,sizeof(f)); dfsLca(s,s); for(int i=0;i<n*m;++i) vt[i].clear(); for(int i=0;i<q;++i) if(q1[i]!=q2[i]) {vt[q1[i]].push_back(i);vt[q2[i]].push_back(i);} memset(ans,0,sizeof(ans)); dfs(s,0,3); for(int i=0;i<q;++i) { if(q1[i]==q2[i]) {cout<<"0"<<endl;continue;} if((k1[i]&k2[i])==0) ++ans[i]; cout<<ans[i]<<endl; } return 0; }