poj 3694 Network側ダブル接続+LCA
4176 ワード
テーマリンク:http://poj.org/problem?id=3694
n個の点、m条の辺、連図をあげます。そしてQ回の操作があります。毎回一つの辺(A、B)を入れて、辺に参加した後、現在どれぐらいの橋があるかを聞きます。出力橋の個数。
問題の構想を解く:まずもとの連通図の辺の双連通を1本の木に縮めて、Q回の操作の過程の中で木に対してLCA操作を行います。コードを具体的に見る:
ネットを見ても縮まない方法があります。
考え方は、http://www.cnblogs.com/kuangbin/p/3184884.html
n個の点、m条の辺、連図をあげます。そしてQ回の操作があります。毎回一つの辺(A、B)を入れて、辺に参加した後、現在どれぐらいの橋があるかを聞きます。出力橋の個数。
問題の構想を解く:まずもとの連通図の辺の双連通を1本の木に縮めて、Q回の操作の過程の中で木に対してLCA操作を行います。コードを具体的に見る:
ネットを見ても縮まない方法があります。
考え方は、http://www.cnblogs.com/kuangbin/p/3184884.html
#include "stdio.h" //poj 3177 + LCA( )
#include "string.h"
#include "vector"
#include "queue"
using namespace std;
#define N 100100
#define M 400200
struct node
{
int x,y;
bool visit;
int next;
} edge[2*M];
int idx,head[N];
void Init()
{
idx = 0;
memset(head,-1,sizeof(head));
}
void Add(int x,int y)
{
edge[idx].x = x;
edge[idx].y = y;
edge[idx].visit = false;
edge[idx].next = head[x];
head[x] = idx++;
}
int time;
int low[N],dfn[N];
inline int MIN(int a,int b)
{
return a<b?a:b;
}
int st[M],num; //
int stackk[2*M],top; // ( , )
int n,m;
int countt; //
int belong[N];
void lian_tong(int x)
{
int t;
countt++;
while(1)
{
t = stackk[top];
top--;
belong[t] = countt;
if(t==x) break;
}
}
void DFS(int x)
{
int i,y;
stackk[++top] = x;
low[x] = dfn[x] = ++time;
for(i=head[x]; i!=-1; i=edge[i].next)
{
y = edge[i].y;
if(edge[i].visit) continue;
edge[i].visit = edge[i^1].visit = true;
if(!dfn[y])
{
DFS(y);
low[x] = MIN(low[x],low[y]);
if(low[y]>dfn[x])
st[num++] = i; // ( )
}
else
low[x] = MIN(low[x],dfn[y]);
}
if(dfn[x]==low[x])
lian_tong(x); //
}
int ans;
bool mark[N];
int deep[N];
int father[N];
vector<int> vec[N]; //
void LCA_bfs(int root)
{
int i,x,y;
memset(deep,-1,sizeof(deep));
deep[root] = 0;
mark[root] = false;
father[root] = -1;
queue<int> q;
q.push(root);
while(!q.empty())
{
x = q.front();
q.pop();
for(i=0; i<(int)vec[x].size(); ++i)
{
y = vec[x][i];
if(deep[y]!=-1) continue;
deep[y] = deep[x]+1;
mark[y] = true;
father[y] = x;
q.push(y);
}
}
}
void swap(int &x,int &y)
{
int t = x;
x = y;
y = t;
}
void LCA(int x,int y)
{
if(deep[x] > deep[y]) swap(x,y);
while(deep[x]<deep[y])
{
if(mark[y])
{
ans--;
mark[y] = false;
}
y = father[y];
}
while(x!=y)
{
if(mark[x])
{
ans--;
mark[x] = false;
}
if(mark[y])
{
ans--;
mark[y] = false;
}
x = father[x];
y = father[y];
}
}
void Solve()
{
int i;
int x,y;
countt = 0; //
num = 0; //
top = 0; //
time = 0;
memset(dfn,0,sizeof(dfn));
DFS(1);
for(i=1; i<=countt; ++i) vec[i].clear();
for(i=0; i<num; ++i) //
{
x = edge[st[i]].x;
y = edge[st[i]].y;
x = belong[x];
y = belong[y];
vec[x].push_back(y);
vec[y].push_back(x);
}
LCA_bfs(1);
ans = countt - 1;
int Q;
int u,v;
scanf("%d",&Q);
while(Q--)
{
scanf("%d %d",&u,&v);
LCA(belong[u],belong[v]);
printf("%d
",ans);
}
printf("
");
}
int main()
{
int i;
int Case=0;
int x,y;
while(scanf("%d %d",&n,&m),n+m)
{
Init();
Case++;
for(i=0; i<m; ++i)
{
scanf("%d %d",&x,&y);
Add(x,y);
Add(y,x);
}
printf("Case %d:
",Case);
Solve();
}
return 0;
}