Codeforces 165D

题意:一幅图,至多有一个点的度数大于2,,然后有三种操作,给每条边染成黑色或白色,询问两个点间的黑色路径的距离是多少(即两个点有黑色路径相连而成)。

找出那个度数大于2的点,没有的话就是一条链。

有几个度就有几条链,对于每个操作,找到每个点相应的链,和这个点是这条链上的第几个点,用树状数组做就可以了。

考察图的模拟,二维树状数组或线段树

学习了别人的代码

View Code
#include<cstdio>
#include<cstring>
#include<vector>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int N = 300010;
vector<int> c[N];
vector<int> edge[N];
int a[N],b[N],ans,n,z[N],col[N];
int rank[N];
void update(int branch,int x,int d){
for(;x<c[branch].size();x+=x&-x)
c[branch][x]+=d;
}
int sum(int branch,int x){
for(ans=0;x;x-=x&-x)
ans+=c[branch][x];
return ans;
}
int max(int a,int b)
{
return a>b?a:b;
}
int main()
{
int i,j,k,op,root,m;
scanf("%d",&n);
for(i=1;i<n;i++)
{
scanf("%d%d",&a[i],&b[i]);
edge[a[i]].push_back(b[i]);
edge[b[i]].push_back(a[i]);
}
root=1;
for(i=1;i<=n;i++)
if(edge[i].size()>2)
{
root=i;break;
}
for(i=0;i<edge[root].size();i++)
{
j=edge[root][i];int pre=root;int tmp=j;int step=0;
while(1)
{
rank[tmp]=i;z[tmp]=++step;
if(edge[tmp].size()<2) break;
int p=edge[tmp][0];
if(p==pre)
p=edge[tmp][1];
pre=tmp;
tmp=p;
}
c[i].resize(step+1,0);//这里忘了写了
}
scanf("%d",&m);
while(m--)
{
scanf("%d%d",&op,&i);
if(op<3)
{
if(col[i]^(op==2))
{
int branch=max(rank[a[i]],rank[b[i]]);
update(branch,max(z[a[i]],z[b[i]]),op==1?-1:1);
col[i]=op-1;
}
}
else
{
scanf("%d",&j);
if(rank[i]==rank[j])
{
if(sum(rank[i],z[i])==sum(rank[j],z[j]))
{
printf("%d\n",abs(z[i]-z[j]));
}
else printf("-1\n");
}
else
{
if(sum(rank[i],z[i])+sum(rank[j],z[j])>0)
{
printf("-1\n");
}
else
{
printf("%d\n",z[i]+z[j]);
}
}
}
}
}



posted @ 2012-03-21 13:24  Because Of You  Views(394)  Comments(0Edit  收藏  举报