zoukankan      html  css  js  c++  java
  • 【BZOJ3331】[BeiJing2013]压力 Tarjan求点双

    【BZOJ3331】[BeiJing2013]压力

    Description

    如今,路由器和交换机构建起了互联网的骨架。处在互联网的骨干位置的核心路由器典型的要处理100Gbit/s的网络流量。他们每天都生活在巨大的压力之下。
    小强建立了一个模型。这世界上有N个网络设备,他们之间有M个双向的链接。这个世界是连通的。在一段时间里,有Q个数据包要从一个网络设备发送到另一个网络设备。
    一个网络设备承受的压力有多大呢?很显然,这取决于Q个数据包各自走的路径。不过,某些数据包无论走什么路径都不可避免的要通过某些网络设备。
    你要计算:对每个网络设备,必须通过(包括起点、终点)他的数据包有多少个?

    Input

    第一行包含3个由空格隔开的正整数N,M,Q。
    接下来M行,每行两个整数u,v,表示第u个网络设备(从1开始编号)和第v个网络设备之间有一个链接。u不会等于v。两个网络设备之间可能有多个链接。
    接下来Q行,每行两个整数p,q,表示第p个网络设备向第q个网络设备发送了一个数据包。p不会等于q。

    Output

    输出N行,每行1个整数,表示必须通过某个网络设备的数据包的数量。

    Sample Input

    4 4 2
    1 2
    1 3
    2 3
    1 4
    4 2
    4 3

    Sample Output

    2
    1
    1
    2

    HINT

    【样例解释】
    设备1、2、3之间两两有链接,4只和1有链接。4想向2和3各发送一个数据包。显然,这两个数据包必须要经过它的起点、终点和1。
    【数据规模和约定】
    对于40%的数据,N,M,Q≤2000
    对于60%的数据,N,M,Q≤40000
    对于100%的数据,N≤100000,M,Q≤200000

    题解:显然先用Tarjan求缩块。。。怎么求呢。。。基本功不扎实又去学了一发。

    最后我们会得到一个树形结构,但是。。。怎么得到呢。。。其实对于每个块新建一个点连向块中的所有点即可。

    然后就是一个类似于树的东西了,怎么统计树上有哪些路径必经一个点呢?差分即可。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    using namespace std;
    const int maxn=200010;
    int n,m,q,top,tot,sum,cnt;
    int sta[maxn],low[maxn],HEAD[maxn],NEXT[maxn<<1],TO[maxn<<1],head[maxn<<1],next[maxn<<2],to[maxn<<2];
    int s[maxn<<1],fa[19][maxn<<1],Log[maxn<<1],dep[maxn<<1],Q[maxn<<1];
    inline void ADD(int a,int b)
    {
    	TO[cnt]=b,NEXT[cnt]=HEAD[a],HEAD[a]=cnt++;
    }
    inline void add(int a,int b)
    {
    	to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
    }
    void tarjan(int x)
    {
    	dep[x]=low[x]=++tot,sta[++top]=x;
    	for(int y,i=HEAD[x],t;i!=-1;i=NEXT[i])
    	{
    		y=TO[i];
    		if(!dep[y])
    		{
    			tarjan(y),low[x]=min(low[x],low[y]);
    			if(low[y]>=dep[x])
    			{
    				sum++;
    				do
    				{
    					t=sta[top--],add(sum,t),add(t,sum);
    				}while(t!=y);
    				add(sum,x),add(x,sum);
    			}
    		}
    		else	low[x]=min(low[x],dep[y]);
    	}
    }
    void dfs(int x)
    {
    	Q[++Q[0]]=x;
    	for(int i=head[x];i!=-1;i=next[i])	if(to[i]!=fa[0][x])	fa[0][to[i]]=x,dep[to[i]]=dep[x]+1,dfs(to[i]);
    }
    inline int lca(int a,int b)
    {
    	int i;
    	if(dep[a]<dep[b])	swap(a,b);
    	for(i=Log[dep[a]-dep[b]];i>=0;i--)	if(dep[fa[i][a]]>=dep[b])	a=fa[i][a];
    	if(a==b)	return a;
    	for(i=Log[dep[a]];i>=0;i--)	if(fa[i][a]!=fa[i][b])	a=fa[i][a],b=fa[i][b];
    	return fa[0][a];
    }
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+gc-'0',gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	//freopen("bz3331.in","r",stdin);
    	n=rd(),m=rd(),q=rd(),sum=n;
    	memset(head,-1,sizeof(head)),memset(HEAD,-1,sizeof(HEAD));
    	int i,j,a,b,c;
    	for(i=1;i<=m;i++)	a=rd(),b=rd(),ADD(a,b),ADD(b,a);
    	cnt=0,tarjan(1),dep[1]=1,dfs(1);
    	for(i=2;i<=sum;i++)	Log[i]=Log[i>>1]+1;
    	for(j=1;(1<<j)<=sum;j++)	for(i=1;i<=sum;i++)	fa[j][i]=fa[j-1][fa[j-1][i]];
    	for(i=1;i<=q;i++)
    	{
    		a=rd(),b=rd(),c=lca(a,b);
    		s[a]++,s[b]++,s[c]--,s[fa[0][c]]--;
    	}
    	for(i=sum;i;i--)	a=Q[i],s[fa[0][a]]+=s[a];
    	for(i=1;i<=n;i++)	printf("%d
    ",s[i]);
    	return 0;
    }
  • 相关阅读:
    最全Redis面试题
    mabatisplus-update
    windows下安装redis并部署服务
    登录方案
    redis
    IntelliJ IDEA Debug模式启动项目
    物流跟踪 调用快递鸟API
    springboot中文官方文档
    国内物流地址
    什么是电磁兼容?什么是EMC设计?
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7535737.html
Copyright © 2011-2022 走看看