LCA比较基础的题,而且貌似自己的代码只是MLE而已,结果没问题 ,而且也只是超了一点~
mark一下别人过的
2168MS | 21700K | 2458B |
#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;
}
对比我忧伤的代码
15663500 | 2015-11-27 12:15:27 | Memory Limit Exceeded | 2874 | 655MS | 33416K | 3751 B | C++ | 20130738 |
15663491 | 2015-11-27 12:14:18 | Memory Limit Exceeded | 2874 | 405MS | 33412K | 3751 B | C++ | 20130738 |
15663480 | 2015-11-27 12:12:29 | Memory Limit Exceeded | 2874 | 670MS | 33216K | 3751 B | G++ | 20130738 |
15663476 | 2015-11-27 12:11:55 | Memory Limit Exceeded | 2874 | 686MS | 33216K | 3807 B | G++ | 20130738 |
/********
hdu2874
2015.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;
}