zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    好文转贴(1) —— 程序员已死 & 程序员平庸or伟大,证据就在代码里&一些鲜为人知的编程事实
    django的两个学习资料
    django的两个学习资料
    POJ2418(BST)
    全局变量、函数原型和Guard macro
    POJ2754(八皇后)
    VC中Windows常用控件的创建和使用
    POJ1088(DP,DFS)
    超前引用
    POJ2715(Water)
  • 原文地址:https://www.cnblogs.com/cenariusxz/p/6598185.html
Copyright © 2011-2022 走看看