【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;
}
posted @ 2019-09-19 22:09  委屈的咸鱼鱼鱼鱼  阅读(176)  评论(0编辑  收藏  举报