• hdu4338 Simple Path


    Everybody knows that totalfrank has absolutely no sense of direction. Getting lost in the university or nearly supermarket is very common for him. We always worry about whether he can find his way back into our sweet base whenever he goes out alone for his class. In general, if totalfrank get lost again, we need to check his starting point and destination just in order to find out where he could be (you know this task is very common for us).
    Unfortunately, poor totalfrank sometimes forgot taking his mobile phone, when this situation happens, we can’t get in touch with him. But it is so lucky that totalfrank can remember places where he had gone before in his trip from his starting point and destination at this trip so that he won’t go to such place again (he can’t remember places which he had gone during his previous trip). As we are all familiar with map, we can find out which place he couldn’t be.
    However, totalfrank can always get lost, doing this same boring work makes us sleepy. So we ask totalfrank for all possible starting point and destination for him, and try to find out how many places he wouldn’t be when he chooses any pair of starting point and destination. Here comes the problem, since our university’s map is so complex (there can be many buildings which can be considered as points in our university, some pair of these point has a way while others hasn’t), we need a program to help us work out this problem.

      1 #pragma comment(linker, "/STACK:102400000,102400000")
      2 #include <string.h>
      3 #include <stdio.h>
      4 #include <math.h>
      5 #include <algorithm>
      6 const int MAXN=1e5+5;
      7 
      8 struct edge{
      9     int u,v,n;
     10 }e1[MAXN*4],e2[MAXN*4];
     11 
     12 int f1[MAXN],f2[MAXN*2],es1,es2;
     13 int n,m,q,tu,tv;
     14 
     15 void addedge1(int u,int v){    
     16     e1[es1].u=u,e1[es1].v=v,e1[es1].n=f1[u],f1[u]=es1++;
     17 }
     18 
     19 void addedge2(int u,int v){
     20     e2[es2].u=u,e2[es2].v=v,e2[es2].n=f2[u],f2[u]=es2++;
     21 }
     22 
     23 int p[MAXN*2];
     24 
     25 int find(int x){return x==p[x]?x:p[x]=find(p[x]);}
     26 
     27 void merge(int x,int y){p[find(x)]=find(y);}
     28 
     29 int sum[MAXN*2],tsum[MAXN*2],dis[MAXN];
     30 int lca_f[MAXN*4],lca_b[MAXN*4],lca_p[MAXN*2],rid;
     31 int dminv[MAXN*4][20],dminid[MAXN*4][20];
     32 
     33 void dp(int u,int f,int dd,int tot){
     34     dis[u]=dd,tsum[u]=tot+sum[u];
     35     lca_f[++rid]=u,lca_b[rid]=dd,lca_p[u]=rid;
     36     for(int i=f2[u];i!=-1;i=e2[i].n){
     37         int v=e2[i].v;
     38         if(v==f)continue;
     39         dp(v,u,dd+1,tot+sum[u]);
     40         lca_f[++rid]=u,lca_b[rid]=dd;
     41     }
     42 }
     43 
     44 void makermq(){
     45     rid=0;
     46     dp(0,-1,0,0);
     47     for(int i=1;i<=rid;i++)dminv[i][0]=lca_b[i],dminid[i][0]=i;
     48     int maxj=(int)(log(rid+1.0)/log(2.0));
     49     for(int j=1;j<=maxj;j++){
     50         int maxi=rid+1-(1<<j);
     51         for(int i=1;i<=maxi;i++){
     52             if(dminv[i][j-1]<dminv[i+(1<<(j-1))][j-1]){
     53                 dminv[i][j]=dminv[i][j-1];
     54                 dminid[i][j]=dminid[i][j-1];
     55             }else{
     56                 dminv[i][j]=dminv[i+(1<<(j-1))][j-1];
     57                 dminid[i][j]=dminid[i+(1<<(j-1))][j-1];
     58             }
     59         }
     60     }
     61 }
     62 
     63 int lca(int x,int y){
     64     if(lca_p[x]>lca_p[y])std::swap(x,y);
     65     x=lca_p[x],y=lca_p[y];
     66     int k=(int)(log(y-x+1.0)/log(2.0));
     67     int xx=dminv[x][k]<dminv[y+1-(1<<k)][k]?dminid[x][k]:dminid[y+1-(1<<k)][k];
     68     return lca_f[xx];
     69 }
     70 
     71 int dfn[MAXN],low[MAXN],cid[MAXN],stk[MAXN],col[MAXN],top,ind,cls,tmp;
     72 int cal[MAXN*2];
     73 
     74 void dfs_cutpnt(int u,int f,int root){
     75     dfn[u]=low[u]=++ind;
     76     int cnt=0;
     77     int flag=0;
     78     for(int i=f1[u];i!=-1;i=e1[i].n){
     79         int v=e1[i].v;
     80         if(v==f&&!flag){flag=1;continue;}
     81         if(!dfn[v]){
     82             cnt++;
     83             dfs_cutpnt(v,u,root);
     84             if(low[v]<low[u])low[u]=low[v];
     85             if(u==root&&cnt>1&&cid[u]==0)cid[u]=++cls,sum[cls]=1;
     86             else if(u!=root&&low[v]>=dfn[u]&&cid[u]==0)cid[u]=++cls,sum[cls]=1;
     87         }else if(dfn[v]<low[u])low[u]=dfn[v];
     88     }
     89 }
     90 
     91 void dfs_tarjan(int u,int f){
     92     low[u]=dfn[u]=++ind;
     93     stk[++top]=u;
     94     int flag=0;
     95     for(int i=f1[u];i!=-1;i=e1[i].n){
     96         int v=e1[i].v;
     97         if(v==f&&!flag){flag=1;continue;}
     98         if(!dfn[v]){
     99             dfs_tarjan(v,u);
    100             if(low[v]<low[u])low[u]=low[v];
    101             if(low[v]>=dfn[u]){
    102                 sum[++cls]=1,col[u]=cls;
    103                 do{
    104                     tmp=stk[top--],col[tmp]=cls,++sum[cls];
    105                     if(cid[tmp]){addedge2(cid[tmp],cls);addedge2(cls,cid[tmp]);merge(cid[tmp],cls);}
    106                 }while(tmp!=v);
    107                 if(cid[u]){addedge2(cid[u],cls);addedge2(cls,cid[u]);merge(cid[u],cls);}
    108             }
    109         }else if(dfn[v]<low[u])low[u]=dfn[v];
    110     }
    111 }
    112 
    113 int size;
    114 
    115 void makegraph(){
    116     //找割点
    117     memset(dfn,0,sizeof dfn);
    118     memset(low,0,sizeof low);
    119     memset(cid,0,sizeof cid);
    120     cls=ind=0;
    121     //找双联通分量并建图
    122     for(int i=0;i<n;i++)dfs_cutpnt(i,-1,i);
    123     memset(dfn,0,sizeof dfn);
    124     memset(low,0,sizeof low);
    125     memset(col,0,sizeof col);
    126     top=ind=0;
    127     for(int i=0;i<n;i++)dfs_tarjan(i,-1);
    128     //将森林补成树,便于dp以及查询
    129     memset(cal,0,sizeof cal);
    130     for(int i=1;i<=cls;i++){
    131         if(cal[find(i)]==0){
    132             cal[find(i)]=1;
    133             addedge2(0,i);
    134         }
    135     }
    136 }
    137 
    138 int main(){
    139     //freopen("test.in","r",stdin);
    140     int cas=1;
    141     while(scanf("%d%d",&n,&m)!=EOF){
    142         memset(f1,-1,sizeof f1);
    143         memset(f2,-1,sizeof f2);
    144         for(int i=0;i<=2*n;i++)p[i]=i;
    145         es1=es2=0;
    146 
    147         for(int i=0;i<m;i++){
    148             scanf("%d%d",&tu,&tv);
    149             addedge1(tu,tv);
    150             addedge1(tv,tu);
    151         }
    152 
    153         //转化成双联通与割点相邻的图
    154         makegraph();
    155         //lca转化成rmq
    156         makermq();
    157 
    158         printf("Case #%d:
    ",cas++);
    159         scanf("%d",&q);
    160         while(q--){
    161             scanf("%d%d",&tu,&tv);
    162             //起点和终点重合
    163             if(tu==tv)printf("%d
    ",n-1);
    164             else{
    165                 //如果是割点的话就一定要用割点对应的点,因为割点会被染成不同的颜色!
    166                 tu=cid[tu]?cid[tu]:col[tu];
    167                 tv=cid[tv]?cid[tv]:col[tv];
    168                 //孤立点或者不在同一个联通块中
    169                 if(tu==0||tv==0||find(tu)!=find(tv)){
    170                     printf("%d
    ",n);
    171                 }else{
    172                     int fa=lca(tu,tv);
    173                     int ans=tsum[tu]+tsum[tv]-2*tsum[fa]+sum[fa];
    174                     ans-=(dis[tu]+dis[tv]-2*dis[fa]);
    175                     printf("%d
    ",n-ans);
    176                 }
    177             }
    178         }
    179         printf("
    ");
    180     }
    181     return 0;
    182 }
    View Code
  • 相关阅读:
    老板也是一个工种,也是一种技能
    用上了ReSharper
    《钟馗伏魔:雪妖魔灵》另类解读
    内部培训-流程图培训
    未来价值是把信息从网上拿下来,而不是放上
    一个人的电影
    2015清明节假期纪实
    十年魔戒
    天使基金资金预期使用表
    项目过程中各阶段应交付的文档
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/6598185.html
Copyright © 2020-2023  润新知