zoukankan      html  css  js  c++  java
  • bzoj3331: [BeiJing2013]压力

    如今,路由器和交换机构建起了互联网的骨架。处在互联网的骨干位置的核心路由器典型的要处理100Gbit/s的网络流量。他们每天都生活在巨大的压力之下。
    小强建立了一个模型。这世界上有N个网络设备,他们之间有M个双向的链接。这个世界是连通的。在一段时间里,有Q个数据包要从一个网络设备发送到另一个网络设备。
    一个网络设备承受的压力有多大呢?很显然,这取决于Q个数据包各自走的路径。不过,某些数据包无论走什么路径都不可避免的要通过某些网络设备。
    你要计算:对每个网络设备,必须通过(包括起点、终点)他的数据包有多少个?
     
     
    题解:比较裸的双联通分量题目;
    首先tarjan求双连通分量,将原图变成一棵树,那么题目要求的就是每个点被多少路径经过,求lca,然后做一个树上差分,判断一下这个点是否是原图的割点,若是,加上经过这一点的路径数;
    不要忘了特判一下每个点起点和终点;
    树链剖分求lca应该更快;
    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<string>
    #include<ctime>
    #include<cmath>
    #include<set>
    #include<map>
    #include<queue>
    #include<algorithm>
    #include<iomanip>
    #include<stack>
    using namespace std;
    #define FILE "dealing"
    #define up(i,j,n) for(int i=(j);i<=(n);i++)
    #define pii pair<int,int>
    #define LL int
    #define mem(f,g) memset(f,g,sizeof(f))
    namespace IO{
    	char buf[1<<15],*fs,*ft;
    	int gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?-1:*fs++;}
    	int read(){
    		int ch=gc(),f=0,x=0;
    		while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=gc();}
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();}
    		return f?-x:x;
    	}
    	int readint(){
    		int ch=getchar(),f=0,x=0;
    		while(ch<'0'||ch>'9'){if(ch=='-')f=1;ch=getchar();}
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
    		return f?-x:x;
    	}
    }using namespace IO;
    const int maxn=201000,inf=100000000;
    int n,m,Q;
    struct node{
    	int y,next;
    }e[maxn],E[maxn];
    int linkk[maxn],len=0,linker[maxn],Len=0;
    inline void insert(int x,int y,int* linkk,int &len,node* e){e[++len].y=y;e[len].next=linkk[x];linkk[x]=len;}
    int x,y,ans[maxn],N=0,last=0,id[maxn],re[maxn];//记录每个点在新图中的编号;
    int u[maxn],v[maxn];
    namespace maketree{
    	vector<int> bcc[maxn];
    	int pre[maxn],low[maxn],iscut[maxn],b[maxn],dfs_clock=0,cnt=0;
    	int u[maxn],v[maxn],top=0;
    	void tarjan(int x,int fa){
    		pre[x]=low[x]=++dfs_clock;int child=0;
    		for(int i=linkk[x];i;i=e[i].next){
    			if(e[i].y==fa)continue;
    			if(!pre[e[i].y]){
    				u[++top]=x,v[top]=e[i].y;
    				tarjan(e[i].y,x);
    				if(low[e[i].y]<low[x])low[x]=low[e[i].y];
    				if(low[e[i].y]>=pre[x]){
    					iscut[x]=1;cnt++;bcc[cnt].clear();
    					while(true){
    						if(b[u[top]]!=cnt){bcc[cnt].push_back(u[top]);b[u[top]]=cnt;}
    						if(b[v[top]]!=cnt){bcc[cnt].push_back(v[top]);b[v[top]]=cnt;}
    						if(u[top]==x&&v[top]==e[i].y){top--;break;}
    						top--;
    					}
    				}
    			}
    			else if(pre[e[i].y]<pre[x]){
    				u[++top]=x,v[top]=e[i].y;
    				if(pre[e[i].y]<low[x])low[x]=pre[e[i].y];
    			}
    		}
    		if(!fa&&child==1)iscut[x]=0;
    	}
    	void slove(){
    		tarjan(1,0);
    		last=N=cnt;
    		int x;
    		up(i,1,cnt){
    			for(int j=0;j<bcc[i].size();j++){
    				x=bcc[i][j];
    				if(iscut[x]){
    					if(!id[x])id[x]=++N,re[id[x]]=x;//缩点后的点对应的实际的点
    					insert(id[x],i,linker,Len,E);
    					insert(i,id[x],linker,Len,E);
    				}
    				else id[x]=i;
    			}
    		}
    	}
    };
    int num[maxn];
    namespace st{
    	int fa[maxn][31],dep[maxn];
    	void dfs(int x,int f){
    		for(int i=linker[x];i;i=E[i].next){
    			if(E[i].y==f)continue;
    			fa[E[i].y][0]=x;
    			dep[E[i].y]=dep[x]+1;
    			dfs(E[i].y,x);
    		}
    	}
    	void getlca(int x,int y){
    		if(dep[y]<dep[x])swap(x,y);
    		int u=x,v=y;
    		for(int i=30;i>=0;i--)
    			if(dep[y]-dep[x]>=(1<<i))y=fa[y][i];
    		if(x==y){
    			num[fa[x][0]]-=1;
    			num[v]+=1;
    			return;
    		}
    		for(int i=30;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    		num[fa[fa[x][0]][0]]-=1;
    		num[fa[x][0]]-=1;
    		num[u]+=1;num[v]+=1;
    	}
    	void slove(){
    		dfs(1,0);
    		up(j,1,30)up(i,1,N)fa[i][j]=fa[fa[i][j-1]][j-1];
    		int x,y;
    		up(i,1,Q){
    			u[i]=x=read(),v[i]=y=read();
    			x=id[x];y=id[y];
    			if(x!=y)getlca(x,y);
    		}
    	}
    };
    int dfs(int x,int fa){
    	int sum=num[x];
    	for(int i=linker[x];i;i=E[i].next){
    		if(E[i].y==fa)continue;
    		sum+=dfs(E[i].y,x);
    	}
    	if(x>last){
    		ans[re[x]]+=sum;
    	}
    	return sum;
    }
    int main(){
    	n=read(),m=read(),Q=read();
    	up(i,1,m){
    		x=read(),y=read();
    		insert(x,y,linkk,len,e);
    		insert(y,x,linkk,len,e);
    	}
    	maketree::slove();
    	st::slove();
    	up(i,1,Q){
    		if(id[u[i]]<=last)ans[u[i]]++;
    		if(id[v[i]]<=last)ans[v[i]]++;
    	}
    	dfs(1,0);
    	up(i,1,n)printf("%d%c",ans[i],i==n?'
    ':' ');
    	return 0;
    }
    

      

  • 相关阅读:
    Win32串口API
    Windows核心编程 第4章 进程
    大家都来吐槽下12306的网站bug吧
    HttpRequest模拟Post和Get提交代码
    jquery.masonry + jquery.infinitescroll 实现瀑布流布局
    三层架构之泛型应用
    listView 中,大图标时,各个图标之间间距的控制
    Windows Phone APP的设计过程
    分享三个小故事
    最值得创业者聆听的10大TED演讲(中文字幕视频)
  • 原文地址:https://www.cnblogs.com/chadinblog/p/6149106.html
Copyright © 2011-2022 走看看