• 3331: [BeiJing2013]压力


    3331: [BeiJing2013]压力

    LCA+树上差分,和之前类似的题差不多,就是多了个v-dcc缩点,唯一要注意的就是判断是否是割点,对于不是割点的点,如果他是起点或重点,ans++,和差分没有关系,对于割点,则需要用到差分,注意割点与非割点的答案要分开存储,否则会死的。

    另外要注意的是数组的大小,开始我因为数组开小了然后MLE了(对,就是这么神奇),因为如果退化成一条链,缩完点后的点数会比缩点前还要多。

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #define MAXN 300010
    using namespace std;
    struct edge
    {
    	int u,v,nxt;
    	#define u(x) ed[x].u
    	#define v(x) ed[x].v
    	#define n(x) ed[x].nxt
    	#define u2(x) ed2[x].u
    	#define v2(x) ed2[x].v
    	#define n2(x) ed2[x].nxt
    }ed[MAXN*4],ed2[MAXN*4];
    int first[MAXN],num_e;
    #define f(x) first[x]
    int first2[MAXN],num_e2;
    #define f2(x) first2[x]
    int n,m,q;
    
    int dfn[MAXN],low[MAXN],num,root;
    int stack[MAXN],top,cnt;
    bool iscut[MAXN];
    vector<int> dcc[MAXN];
    void tarjan(int x)
    {
    	dfn[x]=low[x]=++num;
    	stack[++top]=x;
    	if(x==root&&!f(x)){dcc[++cnt].push_back(x);return;}
    	int flag=0;
    	for(int i=f(x);i;i=n(i))
    	if(!dfn[v(i)])
    	{
    		tarjan(v(i));low[x]=min(low[x],low[v(i)]);
    		if(low[v(i)]>=dfn[x])
    		{
    			flag++;
    			if(x!=root||flag>1)iscut[x]=1;
    			cnt++;int z;
    			do{dcc[cnt].push_back(z=stack[top--]);}while(z!=v(i));
    			dcc[cnt].push_back(x);
    		}
    	}
    	else low[x]=min(low[x],dfn[v(i)]);
    }
    int new_id[MAXN],c[MAXN];
    int f[MAXN][20],dep[MAXN];
    void dfs(int x,int fa,int deep)
    {
    	f[x][0]=fa;dep[x]=deep;
    	for(int i=f2(x);i;i=n2(i))
    	if(v2(i)!=fa)
    		dfs(v2(i),x,deep+1);
    }
    int ans[MAXN],eans[MAXN];
    void dfs2(int x,int fa)
    {
    	for(int i=f2(x);i;i=n2(i))
    	if(v2(i)!=fa)
    	{
    		dfs2(v2(i),x);
    		eans[x]+=eans[v2(i)];
    	}
    }
    int LCA(int x,int y)
    {
    	if(dep[x]>dep[y])swap(x,y);
    	while(dep[x]!=dep[y])
    		for(int i=0;;i++)
    		if(dep[f[y][i]]<dep[x])
    		{y=f[y][i-1];break;}
    	if(x==y)return x;
    	while(f[x][0]!=f[y][0])
    		for(int i=0;;i++)
    		if(f[x][i]==f[y][i])
    		{x=f[x][i-1],y=f[y][i-1];break;}
    	return f[x][0];
    }
    inline void add(int u,int v);
    inline void add2(int u,int v);
    signed main()
    {
    //	freopen("in.txt","r",stdin);
    
    	scanf("%d%d%d",&n,&m,&q);
    	int a,b;
    	for(int i=1;i<=m;i++)
    	{
    		scanf("%d%d",&a,&b);
    		add(a,b),add(b,a);
    	}
    	for(int i=1;i<=n;i++)
    	if(!dfn[i]){root=i;tarjan(i);}
    	num=cnt;
    	for(int i=1;i<=n;i++)
    	if(iscut[i])new_id[i]=++num;
    	for(int i=1;i<=cnt;i++)
    		for(int j=0;j<dcc[i].size();j++)
    		{
    			int x=dcc[i][j];
    			if(iscut[x])
    				 add2(i,new_id[x]),add2(new_id[x],i);
    			else c[dcc[i][j]]=i;
    		}
    	dfs(1,0,1);
    	for(int j=1;j<20;j++)
    		for(int i=1;i<=num;i++)
    		f[i][j]=f[f[i][j-1]][j-1];
    	for(int i=1;i<=q;i++)
    	{
    		scanf("%d%d",&a,&b);
    		if(!iscut[a])ans[a]++;
    		if(!iscut[b])ans[b]++;
    		int ca=iscut[a]?new_id[a]:c[a],
    			cb=iscut[b]?new_id[b]:c[b],
    			lca=LCA(ca,cb);
    		eans[ca]++,eans[cb]++;
    		eans[f[lca][0]]--,eans[lca]--;
    	}
    	dfs2(1,0);
    	for(int i=1;i<=n;i++)
    		printf("%d
    ",iscut[i]?eans[new_id[i]]:ans[i]);
    }
    inline void add(int u,int v)
    {
    	++num_e;
    	u(num_e)=u;
    	v(num_e)=v;
    	n(num_e)=f(u);
    	f(u)=num_e;
    }
    inline void add2(int u,int v)
    {
    	++num_e2;
    	u2(num_e2)=u;
    	v2(num_e2)=v;
    	n2(num_e2)=f2(u);
    	f2(u)=num_e2;
    }
    
  • 相关阅读:
    《大型网站技术架构:核心原理与案分析》阅读笔记05
    软件体系结构(1)
    《大型网站技术架构:核心原理与案分析》阅读笔记04
    C/C++
    NIO蔚来自动驾驶实习生技术一面
    Intern Day86
    面试常考
    中国赛宝实验室C++技术一面
    Intern Day85
    Intern Day85
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11182011.html
Copyright © 2020-2023  润新知