zoukankan      html  css  js  c++  java
  • bzoj 3331: [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

    Source

    mdzz,到今天才会点双缩点。。。(其实也不算缩点,只是通过添加虚拟点使原图转为树)

    对于比较杂乱的图一般都是通过重构变为比较好维护信息的图,

    题目中必经点肯定是割点。。。然后重构成树后就很好维护了。

    以前打的点双没有用栈实现,是求出来后再dfs一遍求出,这样就去掉了图中的割点,导致我后来yy的时候连出了好多环。。。;

    如果用栈实现的话,先把所有的点双求出来,把原图所有边都删去,在新图中,对于每个点双新建一个虚拟点,然后把点双中的所有点向这个虚拟点连无向边;

    因为点双之间是以割点为交连起来的,所以新建图中仍能够保持连通性。有点强劲有力。。。

    建成树后,因为只有一次询问,所以可以树上差分,由于是点的差分,所以和边的差分有所不同:

    是cf[lca]--,使lca只加一次,再cf[fa[lca]]--,是fa[lca]保持不变;

    // MADE BY QT666
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<iostream>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int N=500050;
    int gi(){
      int x=0,flag=1;
      char ch=getchar();
      while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
      while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
      return x*flag;
    }
    int cnt,head[N],nxt[N],to[N],n,m,q,tt,dfn[N],low[N],iscut[N],vis[N],tot,pos[N],vis2[N],rt;
    int size[N],son[N],top[N],deep[N],fa[N],cf[N],ans[N],zhan[N],num,sum;
    vector<int>p[N],bcc[N];
    void lnk(int x,int y){
      to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
      to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt;
    }
    void tarjan(int x){
      dfn[x]=low[x]=++tt;zhan[++sum]=x;
      for(int i=head[x];i;i=nxt[i]){
        int y=to[i];
        if(!dfn[y]){
          tarjan(y);low[x]=min(low[x],low[y]);
          if(low[y]>=dfn[x]){
    	num++;int tmp;
    	do{
    	  tmp=zhan[sum--];
    	  bcc[num].push_back(tmp);
    	}while(tmp!=y);
    	bcc[num].push_back(x);
          }
        }
        else low[x]=min(low[x],dfn[y]);
      }
    }
    void dfs1(int x,int f){
      size[x]=1;deep[x]=deep[f]+1;fa[x]=f;
      for(int i=0;i<p[x].size();i++){
        int y=p[x][i];
        if(y!=f){
          dfs1(y,x);size[x]+=size[y];
          if(size[y]>size[son[x]]) son[x]=y;
        }
      }
    }
    void dfs2(int x,int f){
      top[x]=f;
      if(son[x]) dfs2(son[x],f);
      for(int i=0;i<p[x].size();i++){
        int y=p[x][i];
        if(y!=fa[x]&&y!=son[x]) dfs2(y,y);
      }
    }
    int lca(int x,int y){
      while(top[x]!=top[y]){
        if(deep[top[x]]<deep[top[y]]) swap(x,y);
        x=fa[top[x]];
      }
      if(deep[x]<deep[y]) swap(x,y);
      return y;
    }
    void count(int x){
      for(int i=0;i<p[x].size();i++){
        int y=p[x][i];
        if(y!=fa[x])count(y),cf[x]+=cf[y];
      }
    }
    void rebuild(){
      for(int i=1;i<=num;i++){
        for(int j=0;j<bcc[i].size();j++){
          int x=bcc[i][j];cout<<x<<' ';
          p[x].push_back(i+n);p[i+n].push_back(x);
        }
        cout<<endl;
      }
    }
    int main(){
      n=gi(),m=gi(),q=gi();
      for(int i=1;i<=m;i++){
        int x=gi(),y=gi();lnk(x,y);
      }
      tarjan(1);tot=n;rebuild();
      dfs1(1,0);dfs2(1,1);
      for(int i=1;i<=q;i++){
        int u=gi(),v=gi(),LCA=lca(u,v);
        cf[u]++,cf[v]++,cf[LCA]--,cf[fa[LCA]]--;
      }
      count(1);for(int i=1;i<=n;i++) printf("%d
    ",cf[i]);
      return 0;
    }
    
  • 相关阅读:
    英雄联盟离线更新方法
    (七) Keras 绘制网络结构和cpu,gpu切换
    剑指offer | 链表中的倒数第K个结点 | 12
    剑指offer | 从尾到头打印链表 | 11
    剑指offer | 栈的压入,弹出序列 | 10
    剑指offer | 包含min函数的栈 | 09
    剑指offer | 调整数组顺序使奇数位于偶数前面 | 08
    剑指offer | 旋转数组的最小数字 | 07
    剑指offer | 两个栈实现一个队列 | 06
    剑指offer | 替换空格 | 05
  • 原文地址:https://www.cnblogs.com/qt666/p/6952674.html
Copyright © 2011-2022 走看看