hdu 2460

这是一道双联通分量的题,要用到LCA算法;

听说这个算法有两种实现方式:一个是dfs+线段树或着RMQ;一个是用tarjin;

我用的是tarjin;

题目比较简单,就是每次加了一条边之后剩下的桥的个数;

代码:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 using namespace std;
  6 #define MAXN 100009
  7 #pragma comment(linker,"/STACk:10240000,10240000")
  8 
  9 int n,m,cnt,NE,BridgeNum;
 10 int parent[MAXN],low[MAXN],dfn[MAXN];
 11 bool mark[MAXN],isbridge[MAXN];
 12 vector<int>ve[MAXN];
 13 
 14 void Tarjan(int u,int father)
 15 {
 16     int flag=0;
 17     low[u]=dfn[u]=++cnt;
 18     mark[u]=true;
 19     int l=ve[u].size();
 20     for(int i=0; i<l; i++)
 21     {
 22         int v=ve[u][i];
 23         if(v==father&&!flag)
 24         {
 25             flag=1;
 26             continue;
 27         }
 28         if(dfn[v]==0)
 29         {
 30             parent[v]=u;
 31             Tarjan(v,u);
 32             low[u]=min(low[u],low[v]);
 33             if(low[v]>dfn[u])
 34             {
 35                 isbridge[v]=1;
 36                 BridgeNum++;
 37             }
 38         }
 39         else if(mark[v])
 40             low[u]=min(low[u],dfn[v]);
 41     }
 42 }
 43 
 44 void LCA(int u,int v)
 45 {
 46     while(dfn[u]>dfn[v])
 47     {
 48         if(isbridge[u])
 49         {
 50             BridgeNum--;
 51             isbridge[u]=0;
 52         }
 53         u=parent[u];
 54     }
 55     while(dfn[v]>dfn[u])
 56     {
 57         if(isbridge[v])
 58         {
 59             BridgeNum--;
 60             isbridge[v]=0;
 61         }
 62         v=parent[v];
 63     }
 64     while(u!=v)
 65     {
 66         if(isbridge[u])
 67         {
 68             BridgeNum--;
 69             isbridge[u]=0;
 70         }
 71         if(isbridge[v])
 72         {
 73             BridgeNum--;
 74             isbridge[v]=0;
 75         }
 76         u=parent[u],v=parent[v];
 77     }
 78 }
 79 int main()
 80 {
 81     int u,v,Q,ca=1;
 82     while(scanf("%d%d",&n,&m)&&(n+m))
 83     {
 84         BridgeNum=NE=cnt=0;
 85         for(int i=0; i<=n; i++)
 86             ve[i].clear();
 87         while(m--)
 88         {
 89             scanf("%d%d",&u,&v);
 90             ve[u].push_back(v);
 91             ve[v].push_back(u);
 92         }
 93         memset(isbridge,0,sizeof isbridge);
 94         memset(dfn,0,sizeof dfn);
 95         memset(mark,0,sizeof mark);
 96         for(int i=1; i<=n+1; i++)parent[i]=i;
 97         Tarjan(1,-1);
 98         printf("Case %d:\n",ca++);
 99         scanf("%d",&Q);
100         while(Q--)
101         {
102             scanf("%d%d",&u,&v);
103             LCA(u,v);
104             printf("%d\n",BridgeNum);
105         }
106         printf("\n");
107     }
108     return 0;
109 }
View Code

 

posted @ 2013-09-05 11:04  Yours1103  阅读(206)  评论(0编辑  收藏  举报