您的位置:首页 > 其它

poj 3694 求割边+LCA

2015-07-27 16:04 357 查看
#include <iostream>

#include <cstring>

#include <cmath>

#include <cstdio>

#include <vector>

using namespace std;

#define N 100100

vector<int>v
;

bool isbridge
;

int vis
,dfn
,low
,fa
;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;

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: