【2019.9.16】Za

天天爱跑步

树上差分

咕==

#include<bits/stdc++.h>
using namespace std;
const int N=3e5+10,M=50000+10,inf=0x3f3f3f3f;
int n,m,w[N],ans[N],c1[N<<1],c2[N<<1];
vector<int>a1[N],b1[N],a2[N],b2[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[N],tot=0;
struct edge{int v,nxt;}e[N<<1];
void add(int u,int v){e[++tot]=(edge){v,head[u]},head[u]=tot;}
int dep[N],f[N][25];
void bfs(int u,int fa){
    dep[u]=dep[fa]+1,f[u][0]=fa;
    for(int i=head[u],v;i;i=e[i].nxt)
    if((v=e[i].v)!=fa) bfs(v,u);
}
void prepare(){
    bfs(1,0);
    for(int i=1;i<=20;++i)
        for(int j=1;j<=n;++j)
            f[j][i]=f[f[j][i-1]][i-1];
}
int LCA(int x,int y){
    if(dep[x]<dep[y]) swap(x,y);
    for(int i=20;i>=0;--i)
        if(dep[f[x][i]]>=dep[y]) x=f[x][i];
    if(x==y) return x;
    for(int i=20;i>=0;--i)
    if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    return f[x][0];
}

bool vis[N];
void dfs(int x){
    int w1=c1[dep[x]+w[x]],w2=c2[w[x]-dep[x]+n];
    vis[x]=1;
    for(int i=head[x],v;i;i=e[i].nxt)
    if(!vis[v=e[i].v]) dfs(v);
    for(int i=0;i<a1[x].size();++i) ++c1[a1[x][i]];
    for(int i=0;i<b1[x].size();++i) --c1[b1[x][i]];
    for(int i=0;i<a2[x].size();++i) ++c2[a2[x][i]+n];
    for(int i=0;i<b2[x].size();++i) --c2[b2[x][i]+n];
    ans[x]+=c1[dep[x]+w[x]]-w1+c2[w[x]-dep[x]+n]-w2;
}


int main(){
    freopen("in.txt","r",stdin);
    rd(n),rd(m);
    for(int i=1,u,v;i<n;++i) rd(u),rd(v),add(u,v),add(v,u);
    for(int i=1;i<=n;++i) rd(w[i]);
    prepare();
    for(int i=1,x,y,z;i<=m;++i){
        rd(x),rd(y),z=LCA(x,y);
        a1[x].push_back(dep[x]),
        a2[y].push_back(dep[x]-(dep[z]<<1)),
        b1[f[z][0]].push_back(dep[x]),
        b2[z].push_back(dep[x]-(dep[z]<<1));
    }
    dfs(1);
    for(int i=1;i<=n;++i) printf("%d ",ans[i]);
    return 0;
}

求桥

void tarjan(int u,int ine){
    dfn[u]=low[u]=++idx;
    for(int i=head[u],v;i;i=e[i].nxt){
        if(!dfn[v=e[i].v]) {
            tarjan(v,i),low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u]) bridge[i]=bridge[i^1]=1;
        }
        else if(i!=(ine^1)) low[u]=min(low[u],dfn[v]);
    }
}

求割点

void tarjan(int u){
    dfn[u]=low[u]=++idx;int kid=0;
    for(int i=head[u],v;i;i=e[i].nxt){
        if(!dfn[v=e[i].v]){
            tarjan(v),low[u]=min(low[u],low[v]);
            if(low[v]>=dfn[u])
                if(++kid>1||u!=rt) cut[u]=1;
        }
        else low[u]=min(low[u],dfn[v]);
    }
}

边双连通e-DCC

void tarjan(int u,int ine){
    dfn[u]=low[u]=++idx;
    for(int i=head[u],v;i;i=e[i].nxt){
        if(!dfn[v=e[i].v]) {
            tarjan(v,i),low[u]=min(low[u],low[v]);
            if(low[v]>dfn[u]) bridge[i]=bridge[i^1]=1;
        }
        else if(i!=(ine^1)) low[u]=min(low[u],dfn[v]);
    }
}
int bl[N],dcc;
void dfs(int x){
    bl[x]=dcc;
    for(int i=head[u],v;i;i=e[i].nxt)
        if(!bl[v=e[i].v]&&!bridge[i]) dfs(v);
}
int main(){
    for(int i=1;i<=n;++i)
        if(!bl[i]) ++dcc,dfs(i);
    return 0;
}

点双连通v-DCC

void tarjan(int u){
    dfn[u]=low[u]=++idx,s.push(u);
    if(u==rt&&!head[u]) dcc[++cnt].push_back(u);
    int kid=0;
    for(int i=head[u],v,;i;i=e[i].nxt){
        if(!dfn[v=e[i].v]){
            tarjan(v),low[u]=min(low[u],low[v]);
            if(low[v]>=low[u]){
                if(++kid>1||u!=rt) cut[u]=1;
                ++cnt;int z;
                do{
                    z=s.top(),s.pop();
                    dcc[cnt].push_back(z);
                }while(z!=v)
                    dcc[cnt].push_back(u);
            }
            else low[u]=min(low[u],dfn[v]);
        }
    }
}

[JSOI2010] 连通数

bzoj2208 luogu4306

缩点完后用bitset来统计==

按拓扑序来

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
const int N=2000+10,M=4000000+10,inf=0x3f3f3f3f;
int n;
char ss[N];
bitset<N>f[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[N],hd[N],tot=0,tt=0;
struct edge{int v,nxt;}e[M],E[M];
void Add(int u,int v){E[++tt]=(edge){v,hd[u]},hd[u]=tt;}
void add(int u,int v){e[++tot]=(edge){v,head[u]},head[u]=tot;}

int idx=0,Bcnt=0,dfn[N],low[N],bl[N],sz[N];
stack<int>s;bool inst[N];
void tarjan(int u){
    dfn[u]=low[u]=++idx,s.push(u),inst[u]=1;
    for(int i=head[u],v;i;i=e[i].nxt)
        if(!dfn[v=e[i].v]) tarjan(v),low[u]=Min(low[u],low[v]);
        else if(inst[v]&&dfn[v]<low[u]) low[u]=dfn[v];
    if(dfn[u]==low[u]){
        ++Bcnt;int v;
        do{
            v=s.top(),s.pop(),inst[v]=0,f[Bcnt].set(v);
            bl[v]=Bcnt,++sz[Bcnt];
        }while(u!=v);
    }
}

int Q[N],in[N];
queue<int>q;
void topsort(){
    for(int i=1;i<=Bcnt;++i) if(!in[i]) q.push(i);
    while(!q.empty()){
        int u=q.front();
        q.pop(),Q[++Q[0]]=u;
        for(int i=hd[u],v;i;i=E[i].nxt)
            if(!--in[v=E[i].v]) q.push(v);
    }
    for(int i=Q[0];i;--i)
        for(int j=hd[Q[i]];j;j=E[j].nxt)
            f[Q[i]]|=f[E[j].v];
}

int main(){
    freopen("in.txt","r",stdin);
    rd(n);
    for(int i=1;i<=n;++i){
        scanf("%s",ss+1);
        for(int j=1;j<=n;++j)
            if(ss[j]=='1') add(i,j);
    }
    for(int i=1;i<=n;++i)
    if(!dfn[i]) tarjan(i);
    for(int u=1,v;u<=n;++u)
        for(int i=head[u];i;i=e[i].nxt)
            if(bl[u]!=bl[v=e[i].v]) Add(bl[u],bl[v]),++in[bl[v]];
    int ans=0;
    topsort();
    for(int i=1;i<=Bcnt;++i) ans+=f[i].count()*sz[i];
    printf("%d",ans);
    return 0;
}

缩完点后topsort时DP

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
const int N=100000+10,M=100000 +10,inf=0x3f3f3f3f;
int n,m,in[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[N],hd[N],tot=0,tt=0;
struct edge{int v,w,nxt;}e[M],E[M<<1];
void Add(int u,int v,int w){E[++tt]=(edge){v,w,hd[u]},hd[u]=tt;}
void add(int u,int v,int w){e[++tot]=(edge){v,w,head[u]},head[u]=tot;}
int idx=0,Bcnt=0,dfn[N],low[N],bl[N],sz[N];
stack<int>s;bool inst[N];
void tarjan(int u){
    dfn[u]=low[u]=++idx,s.push(u),inst[u]=1;
    for(int i=head[u],v;i;i=e[i].nxt)
        if(!dfn[v=e[i].v]) tarjan(v),low[u]=Min(low[u],low[v]);
        else if(inst[v]&&dfn[v]<low[u]) low[u]=dfn[v];
    if(low[u]==dfn[u]){
        ++Bcnt;int v;
        do{
            v=s.top(),s.pop(),inst[v]=0;
            bl[v]=Bcnt,++sz[Bcnt];
        }while(u!=v);
    }
}

queue<int>q;
int f[N];
void topsort(){
    q.push(0);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=hd[u],v;i;i=E[i].nxt){
            f[v=E[i].v]=Max(f[v],f[u]+E[i].w);
            if(!--in[v]) q.push(v);
        }
    }
    long long ans=0;
    for(int i=1;i<=Bcnt;++i) ans+=(long long)f[i]*sz[i];
    printf("%lld",ans);
}

int main(){
    freopen("in.txt","r",stdin);
    rd(n),rd(m);
    for(int i=1,opt,x,y;i<=m;++i){
        rd(opt),rd(x),rd(y);
        if(opt==1) add(x,y,0),add(y,x,0);
        else if(opt==2) add(x,y,1);
        else if(opt==3) add(y,x,0);
        else if(opt==4) add(y,x,1);
        else add(x,y,0);
    }
    for(int i=1;i<=n;++i) if(!dfn[i]) tarjan(i);
    for(int u=1;u<=n;++u)
        for(int i=head[u],v;i;i=e[i].nxt){
            if(bl[u]==bl[v=e[i].v]&&e[i].w) return puts("-1"),0;
            else if(bl[u]!=bl[v]) Add(bl[u],bl[v],e[i].w),++in[bl[v]];
        }
    for(int i=1;i<=Bcnt;++i) Add(0,i,1),++in[i];
    topsort();
    return 0;
}

[IOI2008]Island

我太难了 打的时候脑子里一团浆糊

acwing上面要T 洛谷上面可以过

#include<bits/stdc++.h>
using namespace std;
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define ll long long
const int N=1e6+10,M=100000 +10,inf=0x3f3f3f3f;
int n,in[N];
template <class t>void rd(t &x){
    x=0;int w=0;char ch=0;
    while(!isdigit(ch)) w|=ch=='-',ch=getchar();
    while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    x=w?-x:x;
}

int head[N],tot=0;
struct edge{int v,w,nxt;}e[N<<1];
void add(int u,int v,int w){
    e[++tot]=(edge){v,w,head[u]},head[u]=tot,++in[v];
}

int bl[N],Bcnt=0;
queue<int>q;
void bfs(int u){
    q.push(u);
    while(!q.empty()){
        u=q.front(),q.pop();
        for(int i=head[u],v;i;i=e[i].nxt)
            if(!bl[v=e[i].v]) bl[v]=Bcnt,q.push(v);
    }
}

ll dis[N],f[N],a[N],b[N];
void topsort(){
    for(int i=1;i<=n;++i) if(in[i]==1) q.push(i);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=head[u],v;i;i=e[i].nxt)
        if(in[v=e[i].v]>1){
            dis[bl[u]]=Max(dis[bl[u]],f[u]+f[v]+e[i].w),
            f[v]=Max(f[v],f[u]+e[i].w);
            if((--in[v])==1) q.push(v);
        }
    }
}

int Q[N];
bool vis[N];
void dp(int x,int t)
{
    int m=0,i,l=0,r,y=x;
    do{
        a[++m]=f[y];in[y]=1;
        for(i=head[y];i;i=e[i].nxt)
            if(in[e[i].v]>1)
                {y=e[i].v;b[m+1]=b[m]+e[i].w; break;}
    }while(i);
    if(m==2)
    {
        for(i=head[y];i;i=e[i].nxt)
            if(e[i].v==x) {l=max(l,e[i].w);}
        dis[t]=max(dis[t],f[x]+f[y]+l);
        return;
    }
    for(i=head[y];i;i=e[i].nxt)
        if(e[i].v==x) {b[m+1]=b[m]+e[i].w; break;}
    for(i=1;i<m;i++) {a[m+i]=a[i]; b[m+i]=b[m+1]+b[i];}
    Q[l=r=1]=1;
    for(i=2;i<2*m;i++)
    {
        while(l<=r&&i-Q[l]>=m) l++;
        dis[t]=max(dis[t],a[i]+a[Q[l]]+b[i]-b[Q[l]]);
        while(l<=r&&a[Q[r]]+b[i]-b[Q[r]]<=a[i]) r--;
        Q[++r]=i;
    }
}


int main(){
    freopen("in.txt","r",stdin);
    rd(n);ll ans=0;
    for(int i=1,v,w;i<=n;++i) rd(v),rd(w),add(i,v,w),add(v,i,w);
    for(int i=1;i<=n;++i)
    if(!bl[i]) ++Bcnt,bfs(i);
    topsort();
    for(int i=1;i<=n;++i)
    if(in[i]>1&&!vis[bl[i]]) vis[bl[i]]=1,dp(i,bl[i]),ans+=dis[bl[i]];
    printf("%lld",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/lxyyyy/p/11552927.html
za