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;
}

注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
  © 2014-2022 ITdaan.com 联系我们: