zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    Nodejs下载和第一个Nodejs示例
    永久关闭Win10工具栏的TaskbarSearch控件
    对称加密,非对称加密,散列算法,签名算法
    【转】TTL和RS232之间的详细对比
    zlg核心板linux系统中查看系统内存等使用信息
    Power BI后台自动刷新数据报错 The operation was throttled by Power BI Premium because there were too many datasets being processed concurrently.
    剪切板和上传文件内容获取
    CSS, LESS, SCSS, SASS总结
    文字程序
    electron 打包“ERR_ELECTRON_BUILDER_CANNOT_EXECUTE”
  • 原文地址:https://www.cnblogs.com/Al-Ca/p/11182011.html
Copyright © 2011-2022 走看看