HDU2874 Connections between cities 最近公共祖先
第一次按常规的方法求,将所有的查询的u,v,和最近公共祖先都保存起来,然后用tarjan+并查集求最近公共祖先。因为询问的次数过多,所以在保存查询的时候总是MLE,后来参考了一下别人的代码,才突然觉悟,可以先将u,v,和其最近公共祖先保存到数组,然后再求结果,为什么不能直接保存其结果了。如果只保存结果的话,保存查询操作就可以节约1/3的内存,所以基本可以过了。
代码如下:
方法一:
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int maxn = 10100; vector<pair<int,int> >tree[maxn],query[maxn]; int father[2][maxn],res[1000010],dis[maxn],vis[maxn]; void init(int n) { memset(vis,0,sizeof(vis)); memset(dis,0,sizeof(dis)); memset(res,-1,sizeof(res)); for( int i = 0; i <= n; i++){ tree[i].clear(); query[i].clear(); father[0][i] = father[1][i] = i; } } int find(int x,int k){ if( x != father[k][x]) return father[k][x] = find(father[k][x],k); return father[k][x]; } void LCA(int u){ vis[u] = 1; pair<int,int>x; int i,size = query[u].size(); for( i = 0; i < size; i++){ x = query[u][i]; if( vis[x.first]) res[x.second] = dis[u] + dis[x.first] - 2*dis[find(x.first,0)]; } size = tree[u].size(); for( i = 0; i < size; i++){ x = tree[u][i]; if( !vis[x.first] ){ dis[x.first] = dis[u] + x.second; LCA(x.first); union_set(x.first,u,0); } } } void union_set(int x,int y,int k){ x = find(x,k); y = find(y,k); if ( x != y) father[k][x] = father[k][y]; } int main() { int n,m,c; int u,v,d; int i; // freopen("in.txt","r",stdin); while( ~scanf("%d%d%d",&n,&m,&c) ){ init(n); while( m-- ){ scanf("%d%d%d",&u,&v,&d); union_set(u,v); tree[u].push_back(make_pair(v,d)); tree[v].push_back(make_pair(u,d)); } for( i = 0; i < c; i++){ scanf("%d%d",&u,&v); if( find(u,1) != find(v,1))continue; query[u].push_back(make_pair(v,i)); query[v].push_back(make_pair(u,i)); } for( i = 1; i <= n; i++){ if( !vis[i] ) LCA(i); } for( i = 0; i < c; i++) if( res[i] == -1)puts("Not connected"); else printf("%d\n",res[i]); } return 0; }
方法二:
#include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <algorithm> using namespace std; const int maxn = 10100; int anc[maxn],dis[maxn],deep[maxn],vis[maxn],fa[maxn]; vector<pair<int,int> >tree[maxn]; void init(int n) { memset(vis,0,sizeof(vis)); for( int i = 1; i <= n; i++){ fa[i] = i; tree[i].clear(); } } void dfs(int u,int now_fa,int now_anc,int now_deep,int now_len) { fa[u] = now_fa; anc[u] = now_anc; vis[u] = u; deep[u] = now_deep; dis[u] = now_len; for( int i = 0; i < tree[u].size() ; i++) { pair<int,int>x = tree[u][i]; if( !vis[x.first] ) dfs(x.first,u,now_anc,now_deep+1,now_len+x.second); } } int find(int x,int y){ if( x == y)return x; if( deep[x] > deep[y]) return find(fa[x],y); else return find(x,fa[y]); } int main() { int n,m,c; int u,v,d; int i; while( ~scanf("%d%d%d",&n,&m,&c)){ init(n); while( m-- ){ scanf("%d%d%d",&u,&v,&d); tree[u].push_back(make_pair(v,d)); tree[v].push_back(make_pair(u,d)); } for( i = 1; i <= n; i++ ) if(!vis[i]) dfs(i,-1,i,0,0); for( i = 0; i < c; i++){ scanf("%d%d",&u,&v); if(anc[u] != anc[v])puts("Not connected"); else printf("%d\n",dis[u]+dis[v] - 2*dis[find(u,v)]); } } return 0; }