最近真的是连切水题都切不来了,
这个题的输入有点恶心。。
但是算法并不难,我用倍增lca水过了;
所谓倍增lca,就是用一个fa【x】【i】数组,记录离x这个节点网上2^i的节点是哪个。
fa【x】【i】=fa【fa【x】【i-1】】【i-1】;
话说Poj现在真是各种崩坏,只能转投zoj或者hdu了。。
附ZOJ1141代码,据说POJ加了新数据,导致过了ZOJ不一定能过POJ,所以换tarjan过poj了,但是理论上这个算法应该是也行的。。。请大牛教做人。。看看这个算法为什么过不了POJ
#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
vector <int> g[2100];
int fa[2100][51],sum[2100],deep[2100];
void dfs(int v,int u,int d)
{
deep[v]=d;
for (int i=0;i<g[v].size();i++)
{
int tmp=g[v][i];
if (tmp==u) continue;
dfs(tmp,v,d+1);
}
}
int lca(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
int t=deep[x]-deep[y];
for (int i=0;i<=20;i++)
if (t&(1<<i)) x=fa[x][i];
if (x==y) return x;
for (int i=0;i<=20;i++)
if (fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int main()
{
freopen("poj1470.in","r",stdin);
freopen("poj14702.out","w",stdout);
int n,tmp_n,u,v,root,q;
while (scanf("%d",&n)==1)
{
for (int i=1;i<=n;i++) {g[i].clear();fa[i][0]=-1;sum[i]=0;}
for (int i=1;i<=n;i++)
{
scanf("%d:(%d)",&u,&tmp_n);
for (int i=1;i<=tmp_n;i++)
{
scanf("%d",&v);
g[u].push_back(v);
g[v].push_back(u);
fa[v][0]=u;
}
}
for (int i=1;i<=n;i++)
if (fa[i][0]==-1)
root=i;
dfs(root,-1,1);
for (int i=1;i<=20;i++)
for (int j=1;j<=n;j++)
fa[j][i]=fa[fa[j][i-1]][i-1];
scanf("%d",&q);
char str[30];
while(q--)
{
int x1,y1;
scanf("%s",str);
sscanf(str,"(%d,%d)",&x1,&y1);
sum[lca(x1,y1)]++;
}
for (int i=1;i<=n;i++)
if (sum[i]>0)
printf("%d:%d\n",i,sum[i]);
}
return 0;
}
存图vector还是好用