ZOJ4097 Rescue the Princess (+ tarjan bis disjoint-set communication component condensing point multiplication algorithm + LCA)

Meaning of the questions:

Gives an undirected graph, each interrogation given three points u, v, w, can find the path to ask where u and v from w, and the two paths do not coincide.

answer:

FIG necessarily communication, when v, w u has not with any one of a communication block, then No direct output (determined with disjoint-set)

Tarjan then condensing point algorithm, each component of a double-point communication, to establish a new graph, since the figures are not necessarily communicating, it can be regarded as the forest.

For each tree in the forest have to do it again LCA pretreatment for discussion after each interrogation classification, there are three legal situation:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+14;
int N,M,Q;
int father[30][maxn];
int h[maxn];
Vector < int > G [MAXN]; // picture 
Vector < int > SC [MAXN]; // after condensing point tarjan FIG 
 @ doubling find the LCA 
int Visit [MAXN];
 void DFS ( int X, int U) {
    visit[x]=1;
    h[x]=h[u]+1;
    father[0][x]=u;
    for (int i=1;(1<<i)<=h[x];i++) 
        father[i][x]=father[i-1][father[i-1][x]];
    for (int i=0;i<sc[x].size();i++) {
        int v=sc[x][i];
        if (v==father[0][x]) continue;
        dfs(v,x);
    }
}
int lca (int x,int y) {
    if (h[x]>h[y]) swap(x,y);
    for (int i=20;i>=0;i--) 
        if (h[x]<=h[y]-(1<<i)) y=father[i][y];
    if (x==y) return x;
    for (int i=20;i>=0;i--) {
        if (father[i][x]!=father[i][y]) {
            x=father[i][x];
            y=father[i][y];
        }
    }
    return father[0][x];
}
// disjoint-set determination block communication 
int F [MAXN];
 int findfather ( int X) {
     int A = X;
     the while (X = F [X]!) X = F [X];
     the while ! (A = F [ A]) {
         int Z = A;
        a=f[a];
        f[z]=x;
    }
    return x;
}
void Union (int a,int b) {
    int faA=findfather(a);
    int faB=findfather(b);
    if (faA!=faB) f[faA]=faB;
}
// Tarjan double condensing point communication component 
int Low [MAXN];
 int DFN [MAXN];
 int POS [MAXN];
 int SCC = 0 ;
 int CNT;
stack<int> st;
void tarjan (int x,int pre) {
    low[x]=dfn[x]=++cnt;
    st.push(x);
    int son=0;
    for (int i=0;i<g[x].size();i++) {
        if (g[x][i]==pre&&++son<2) continue;
        if (!low[g[x][i]]) {
            tarjan(g[x][i],x);
            low[x]=min(low[x],low[g[x][i]]);
        }
        else if (!pos[g[x][i]]) 
            low[x]=min(low[x],dfn[g[x][i]]);
    }
    if (low[x]==dfn[x]) {
        scc++;
        while (1) {
            int u=st.top();
            st.pop();
            low[u]=low[x];
            pos[u]=scc;
            if (u==x) break;
        }
    }
} 

//建立缩点图
void build_sc () {
    for (int i=1;i<=N;i++) {
        for (int j=0;j<g[i].size();j++) 
            if (pos[i]!=pos[g[i][j]])
                sc[pos[i]].push_back(pos[g[i][j]]);
    }
} 
int main () {
    int T;
    scanf("%d",&T);
    while (T--) {
        scanf("%d%d%d",&N,&M,&Q);
        for (int i=1;i<=N;i++)
            g[i].clear(),f[i]=i,sc[i].clear();
        memset(father,0,sizeof(father));
        memset(h,0,sizeof(h));
        memset(visit,0,sizeof(visit));
        scc=0;
        cnt=0;
        fill(low,low+maxn,0);
        fill(dfn,dfn+maxn,0);
        fill(pos,pos+maxn,0);
        while (!st.empty()) st.pop();
        for (int i=0;i<M;i++) {
            int x,y; 
            scanf("%d%d",&x,&y);
            g[x].push_back(y);
            g[y].push_back(x);
            Union (x, y);
        }
        for (int i=1;i<=N;i++) 
            if (!dfn[i]) tarjan(i,i);
        build_sc(); 
        for (int i=1;i<=scc;i++) 
             if (!visit[i]) dfs(i,i);
        for (int i=0;i<Q;i++) {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            int faU=findfather(u);
            int faV=findfather(v);
            int faW=findfather(w);
            u=pos[u];
            v = pos [v];
            w=pos[w];
            //printf("%d %d %d\n",u,v,w);
            if (faU!=faV||faU!=faW) {
                printf("No\n");
                continue;
            }
            int flag=1;
            int uv=lca(u,v);
            int uw=lca(u,w);
            int vw=lca(v,w);
            if (uv==u) {
                if (uw==u&&vw==u) flag=1;
                else if (uw!=u) flag=1;
                else flag=0;
            }
            else if (uv==v) {
                if (uw==u) flag=1;
                else flag=0;
            }
            else {
                 if (your = you!) flag = 0 ;
            }
            if (flag) printf("Yes\n");
            else printf("No\n");
        }
    } 
    return 0;
}

 

Guess you like

Origin www.cnblogs.com/zhanglichen/p/12499138.html