15145641

  其实这是一个裸求LCA的题目,我使用的是离线的Tarjan算法,但是这个题的AC对于我来说却很坎坷……首先是RE,我立马想到数组开小了,然后扩大了数组,MLE了……接着把数组调整适当大小,又交了一发,嗯?居然WA了,一定是我姿势不对,我换个编译器交一下,结果还是WA……这就比较尴尬了,最后审题目,发现了,我以为第一个输入的点就是根节点,其实不是,我们还需要找到入度为0的点来处理,这里做一个标记就可以了。还有就是题目的输入稍微有点坑,尤其是第二次输入,题目中说忽略所有空白,这就需要比较好的处理方法了,我采用的是while的方法,当然方法肯定是有很多的。代码如下:

#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
#define N 1010
int head[N],qhead[N],n,tot,qtot;
struct Edge{
    int to,nxt;
}edge[N*N];
void addedge(int a,int b){
    edge[tot].to = b;
    edge[tot].nxt = head[a];
    head[a] = tot++;
}
Edge query[N*N];
void addquery(int a,int b){
    query[qtot].to = b;
    query[qtot].nxt = qhead[a];
    qhead[a] = qtot++;
}
int vis[N],fa[N],ans[N];
int Find(int x){
    return x == fa[x] ? fa[x] : fa[x] = Find(fa[x]);
}
void tarjan(int u){
    vis[u] = 1;
    fa[u] = u;
    int v,LCA;
    for(int i = qhead[u];i != -1;i = query[i].nxt){
        v = query[i].to;
        if(vis[v]){
            LCA = Find(v);
            //printf("%d->%d LCA = %d\n",u,v,LCA);
            ans[LCA]++;
        }
    }
    for(int i = head[u];i != -1;i = edge[i].nxt){
        v = edge[i].to;
        if(!vis[v]){
            tarjan(v);
            fa[v] = u;
        }
    }
    return ;
}
int main(){
    int a,b,m,num,anc,mark[N];
    while(~scanf("%d",&n)){
        tot = 0;
        memset(head,-1,sizeof(head));
        memset(mark,0,sizeof(mark));
        for(int i = 1;i <= n;i++){
            scanf("%d:(%d) ",&a,&num);
            for(int j = 0;j < num;j++){
                scanf("%d",&b);
                mark[b] = 1;
                addedge(a,b);
            }
//            for(int j = head[a];j != -1;j = edge[j].nxt){
//                printf("%d->%d\n",a,edge[j].to);
//            }
            fa[i] = i;
        }
        for(int i = 1;i <= n;i++){
            if(!mark[i]){
                anc = i;
                break;
            }
        }
        memset(qhead,-1,sizeof(qhead));
        qtot = 0;
        scanf("%d",&m);
      //  getchar();
        char ch; int cnt = 0;
        while(~scanf("%c",&ch)){
            if(ch == '('){
                scanf("%d %d)",&a,&b);
                addquery(a,b);
                addquery(b,a);
                cnt++;
            }
            if(cnt==m) break;
        }
        memset(vis,0,sizeof(vis));
        memset(ans,0,sizeof(ans));
        tarjan(anc);
        for(int i = 1;i <= n;i++){
            if(ans[i]) printf("%d:%d\n",i,ans[i]);
        }
    }
    return 0;
}

 

posted on 2016-06-17 14:30  icode-xiaohu  阅读(281)  评论(0编辑  收藏  举报