poj 3694 求割边+LCA

#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdio>
#include <vector> 
using namespace std;
#define N 100100
vector<int>v[N];
bool isbridge[N];
int vis[N],dfn[N],low[N],fa[N];int ans,index;
void LCA(int x,int y)
{


while(dfn[y]<dfn[x])
{
if(isbridge[x])
isbridge[x]=0,ans--;
x=fa[x];
}
while(dfn[x]<dfn[y])
{
if(isbridge[y])
isbridge[y]=0,ans--;
y=fa[y];
}
while(x!=y)
{
if(isbridge[x])isbridge[x]=0,ans--;
if(isbridge[y])isbridge[y]=0,ans--;
x=fa[x];
y=fa[y];
}
}
void tarjan(int x)
{
int y;
low[x]=dfn[x]=++index;
vis[x]=1;
for(int i=0;i<v[x].size();i++)
{
y=v[x][i];
if(y!=fa[x])
{
if(vis[y]==1)//儿子节点还在栈中,就与儿子节点比较; 
low[x]=min(dfn[y],low[x]);
else if(vis[y]==0)//或者是dfn[x]==0;两者是一样的,表示还未没搜索过;
{
fa[y]=x;
tarjan(y);
low[x]=min(low[x],low[y]); //更新当前节点 
if(dfn[x]<low[y])//表示边x-y是桥; 
{
isbridge[y]=1;
ans++;
   }
}
}
}
vis[x]=2;
return ;
}
int main()
{
int n,m,k,a,b;int q=1;
while(cin>>n>>m)

if(n==0&&m==0)
break;
for(int i=1;i<=n;i++)
v[i].clear();
for(int i=0;i<m;i++)
{
scanf("%d %d",&a,&b);
v[a].push_back(b);
v[b].push_back(a);
}
cin>>k;
index=0;ans=0;
memset(vis,0,sizeof(vis));
memset(fa,0,sizeof(fa));
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
memset(isbridge,0,sizeof(isbridge));
tarjan(1);
// for(int i=1;i<=n;i++)
// cout<<low[i]<<" ";
// cout<<endl;
cout<<"Case "<<q++<<":"<<endl;
while(k--)
{
   scanf("%d %d",&a,&b);
                 LCA(a,b);
                 cout<<ans<<endl; 
}
}
return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值