hdu2874Connections between cities【LCA tarjan】

来源:互联网 发布:屏幕下指纹识别 知乎 编辑:程序博客网 时间:2024/06/08 06:01

LCA比较基础的题,而且貌似自己的代码只是MLE而已,结果没问题 ,而且也只是超了一点~

mark一下别人过的
2168MS21700K2458B

#include <cstdio>#include <algorithm>#include <string>#include <cstring>#include <stack>#include <cmath>#include <queue>#include <list>#include <cstdlib>#include <vector>#include <set>#include <map>#include <sstream>#include <iostream>#include <stack>using namespace std;int n,m,q;struct Node{    int e,xia,val;}e1[20001];struct Node2{    int e,xia;}e2[2000001];int d1,d2,head1[10001],head2[10001];bool vis[10001];int fat[10001],dis[10001],ans[1000001];//所有答案记录在ans数组里。void add1(int s,int e,int val){    e1[d1].e=e,e1[d1].val=val,e1[d1].xia=head1[s];    head1[s]=d1++;}void add2(int s,int e){    e2[d2].e=e,e2[d2].xia=head2[s];    head2[s]=d2++;}int find(int num){    if(fat[num] == num)return num;    return fat[num]=find(fat[num]);}void Union(int s,int e){    fat[e]=s;}void tarjan(int s){    int i;    vis[s]=true;    fat[s]=s;    for(i=head1[s];i != -1;i=e1[i].xia)    {        if(!vis[e1[i].e])        {            dis[e1[i].e]=dis[s]+e1[i].val;            tarjan(e1[i].e);            Union(s,e1[i].e);        }    }    for(i=head2[s];i != -1 ;i=e2[i].xia)    {        if(vis[e2[i].e])        {            if(dis[e2[i].e] != -1)            {                ans[i/2]=dis[s]+dis[e2[i].e]-2*dis[find(e2[i].e)];            }            else ans[i/2]=-1;        }    }}int main(){    int i,j,ji1,ji2,ji3;    while(~scanf("%d %d %d",&n,&m,&q))    {        d1=d2=0;        memset(head1,-1,sizeof(head1));        memset(head2,-1,sizeof(head2));        for(i=0;i<m;i++)        {            scanf("%d %d %d",&ji1,&ji2,&ji3);            add1(ji1,ji2,ji3);            ji1^=ji2,ji2^=ji1,ji1^=ji2;            add1(ji1,ji2,ji3);        }        for(i=0;i<q;i++)        {            scanf("%d %d",&ji1,&ji2);            add2(ji1,ji2);            ji1^=ji2,ji2^=ji1,ji1^=ji2;            add2(ji1,ji2);        }        memset(vis,false,sizeof(vis));        for(i=1;i<=n;i++)fat[i]=i;        for(i=1;i<=n;i++)        {            if(!vis[i])            {                memset(dis,-1,sizeof(dis));                dis[i]=0;                tarjan(i);            }        }        for(i=0;i<q;i++)        {            if(ans[i] == -1)puts("Not connected");            else printf("%d\n",ans[i]);        }    }    return 0;}

对比我忧伤的代码

156635002015-11-27 12:15:27Memory Limit Exceeded2874655MS33416K3751 BC++20130738156634912015-11-27 12:14:18Memory Limit Exceeded2874405MS33412K3751 BC++20130738156634802015-11-27 12:12:29Memory Limit Exceeded2874670MS33216K3751 BG++20130738156634762015-11-27 12:11:55Memory Limit Exceeded2874686MS33216K3807 BG++20130738

/********hdu28742015.11.27********/#include <iostream>#include <stdio.h>#include <algorithm>#include <string.h>#pragma warning(disable:4996)using namespace std;const int maxn=10000;//顶点数const int maxq=1000000;//最多查询次数,根据题目而定.int t;int n,u,v,len,m,c;//并查集int f[maxn];//根节点int find(int x){    if(f[x]==x)        return x;    return f[x]=find(f[x]);}void unite(int u,int v){    int x=find(u);    int y=find(v);    if(x!=y)        f[x]=y;}//并查集结束bool vis[maxn];//节点是否访问int ancestor[maxn];//节点i的祖先struct Edge{    int to,next,len;}edge[maxn*2];int head[maxn],tot;void addedge(int u,int v,int length)//邻接表头插法加边{    edge[tot].to=v;    edge[tot].len=length;  //  printf("%d  ",length);    edge[tot].next=head[u];    head[u]=tot++;}struct Query{    int q,next;    int index;//查询编号,也就是输入的顺序}query[maxq*2];int ans[maxq];//存储每次查询的结果,下表0~Q-1,其实应该开maxq大小的。int h[maxq],tt;int Q;//题目中需要查询的次数int dis[maxn];void addquery(int u,int v,int index)//邻接表头插法加询问{    query[tt].q=v;    query[tt].next=h[u];    query[tt].index=index;    h[u]=tt++;    query[tt].q=u;//相当于两次查询,比如查询  3,5 和5,3结果是一样的,以3为头节点的邻接表中有5,以5为头节点的邻接表中有3    query[tt].next=h[v];    query[tt].index=index;    h[v]=tt++;}void init(){    tot=0;    memset(head,-1,sizeof(head));    tt=0;    memset(h,-1,sizeof(h));    memset(vis,0,sizeof(vis));    for(int i=1;i<=n;i++) f[i]=i;    memset(ancestor,0,sizeof(ancestor));    memset(dis,0,sizeof(dis));    memset(ans,0,sizeof(ans));}void LCA(int u){    ancestor[u]=u;    vis[u]=true;    for(int i=head[u];i!=-1;i=edge[i].next)//和顶点u相关的顶点    {        int v=edge[i].to;       // printf("%d    ",edge[i].len);        if(vis[v])            continue;        //dis[v]+=edge[i].len;        dis[v]=dis[u]+edge[i].len;        LCA(v);        unite(u,v);        ancestor[find(u)]=u;//将u的左右孩子的祖先设为u        //dis[find(u)]+=dis[u];    }    for(int i=h[u];i!=-1;i=query[i].next)//看输入的查询里面有没有和u节点相关的    {        int v=query[i].q;        if(vis[v])            ans[query[i].index]=ancestor[find(v)];    }}bool flag[maxn];//用来确定根节点的int main(){    int a,b,c;    freopen("cin.txt","r",stdin);   // scanf("%d(%d):%d",&a,&b,&c);   // cout<<a<<b<<c;  //  scanf("%d",&t);    while(~scanf("%d%d%d",&n,&m,&c))    {        init();        memset(flag,0,sizeof(flag));        for(int i=1;i<=m;i++)        {            scanf("%d%d%d",&u,&v,&len);            flag[v]=true;//有入度            addedge(u,v,len);            addedge(v,u,len);          //  unite(u,v);        }       // for(int i=1;i<=n;i++) printf("i=%d  f=%d  ",i,f[i]);        for(int i=0;i<c;i++)        {            scanf("%d%d",&u,&v);            addquery(u,v,i);        }        int root;        for(int i=1;i<=n;i++)        {            if(f[i]==i)            {                root=i;//            //    printf("root=%d  ",root);                LCA(root);                f[i]=i;                //break;            }        }        //for(int i=1;i<=n;i++)printf("%d  ",dis[i]); printf("\n");        for(int i=0;i<c;i++)        {            //if(f[query[i<<1].q]!=f[query[i<<1|1].q])            if(f[query[i<<1].q]!=f[query[i<<1|1].q])            {                puts("Not connected");                continue;            }            len=dis[query[i<<1].q]+dis[query[i<<1|1].q]-dis[ans[i]]*2;            printf("%d\n",len);        }    }    return 0;}


0 0
原创粉丝点击