【hackerrank】World CodeSprint 11 T4

题目大意

给出一个n个点有向图及q个操作
1:给出x、d,加入第n+1个点,并与x相连,d=0表示从x练到n+1,d=1表示从n+1练到x;
2:给出x、y,询问从x出发能否到y;

解题思路

在原图上Tarjan缩环,它就变成了一个DAG,用bitset维护点与点之间的连通性;
然后之后连接上去的点不会再构成新的环,所以询问就变成了树上的问题。

#include
#include
#include
#include
#define maxn 50006
#define fr(i,a,b) for(i=a;i<=b;i++)
using namespace std;
using std::bitset;
typedef long long ll;


bitset bits[maxn];
struct poi
{
    int x;
    poi *nex;
} *a[maxn],*b[maxn];

int i,n,m,q,x,y,z,tot,top,col,sum[maxn],dep[maxn],bel[maxn];
int dfn[maxn],low[maxn],sta[maxn],c[maxn],f[maxn],ind[maxn];
bool kan[maxn];
void link(int x,int y)
{
    poi *p=new poi;
    p->x=y;
    p->nex=a[x];
    a[x]=p;
    return;
}
void linkk(int x,int y)
{
    poi *p=new poi;
    p->x=y;
    p->nex=b[x];
    b[x]=p;
    return;
}
void tarjan(int x)
{
    poi *p=new poi;
    dfn[x]=low[x]=++tot;
    sta[++top]=x,kan[x]=1;
    for(p=a[x];p;p=p->nex)
        if (!dfn[p->x])
        {
            tarjan(p->x);
            low[x]=min(low[x],low[p->x]);
        } else if (kan[p->x]) 
            low[x]=min(low[x],dfn[p->x]);
    if (dfn[x]==low[x])
    {
        ++col;
        while (sta[top]!=x)
        {
            c[sta[top]]=col;
            kan[sta[top--]]=0;
        }
        c[x]=col,kan[x]=0,--top;
    }
    return;
}
void ahah()
{
    poi *p=new poi;
    int i,j=0,u;
    fr(i,1,n)
    {
        bits[i][i]=1;
        if (!ind[i]) f[++j]=i,kan[i]=1;
    }
    i=0;
    while (ifor(p=b[u];p;p=p->nex)
        {
            bits[p->x]|=bits[u];
            if (!kan[p->x])
                f[++j]=p->x,kan[p->x]=1;
        }
    }
    return;
}
int main()
{
    freopen("fou.in","r",stdin);
    scanf("%d%d",&n,&m);
    fr(i,1,m)
    {
        scanf("%d%d",&x,&y);
        link(x,y);
    }
    fr(i,1,n) 
        if (!dfn[i]) tarjan(i);
    poi *p=new poi;
    fr(i,1,n)
        for(p=a[i];p;p=p->nex)
            linkk(c[p->x],c[i]),++ind[c[i]];
    memset(kan,0,sizeof(kan));
    ahah();
    scanf("%d",&q);
    fr(i,1,n) bel[i]=c[i];
    fr(i,1,q)
    {
        scanf("%d%d%d",&z,&x,&y);
        if (z==1)
        {
            bel[++n]=bel[x];
            sum[n]=sum[x]+y;
            dep[n]=dep[x]+1;
        } else
        {
            if (c[x] && c[y])
                printf(bits[c[x]].test(c[y])?"Yes\n":"No\n");
            else if (!c[x] && c[y])
            {
                if (sum[x]==dep[x] && bits[bel[x]].test(c[y])) 
                    printf("Yes\n");
                else printf("No\n");
            } else if (c[x] && !c[y])
            {
                if (sum[y]==0 && bits[c[x]].test(bel[y])) 
                    printf("Yes\n");
                else printf("No\n");
            } else if (!c[x] && !c[y])
            {
                if (bel[x]==bel[y])
                {
                    if (dep[x]>dep[y] && (sum[x]-sum[y])==(dep[x]-dep[y]))
                        printf("Yes\n");
                    else if (dep[y]>dep[x] && (sum[y]-sum[x])==0)
                        printf("Yes\n");
                    else printf("No\n");
                } else 
                {
                    if (sum[x]==dep[x] && bits[bel[x]].test(bel[y]) && sum[y]==0)
                        printf("Yes\n");
                    else printf("No\n");
                }
            }
        }
    }
    return 0;
}

你可能感兴趣的:(bitset,Tarjan,hackerrank)