hdu4674 Trip Advisor,双连通分量,LCA
来源:互联网 发布:数据库的储存过程 编辑:程序博客网 时间:2024/05/16 15:37
这鸟题真是写吐了。
简单来说就是缩圈后成为一个树,然后就变成询问树上某条路径path[a,b]是否包含某点c。
这里我想屎了,用的主席树,空间卡到死各种改,虽然还是给我搞过去了,但是代码量……其实只要用lca搞一下就ok。
但是,没那么简单,不仅要在缩点后的路径上,还得求出路径在a、b、c、lca块的出、入点。
简单来说就是缩圈后成为一个树,然后就变成询问树上某条路径path[a,b]是否包含某点c。
这里我想屎了,用的主席树,空间卡到死各种改,虽然还是给我搞过去了,但是代码量……其实只要用lca搞一下就ok。
但是,没那么简单,不仅要在缩点后的路径上,还得求出路径在a、b、c、lca块的出、入点。
挺复杂的判断才能判断是否能有一个不重复点的路径。详情见代码吧。长度真是不忍直视。
#include<iostream>#include<cstdio>#include<cstring>#include<vector>using namespace std;#define NN 100010struct edge{ int v,ne,g;}ed[NN*3];typedef pair<int,int> pii;vector<pii> he;int sta[NN],top;int totb,totdfn,dfn[NN],block[NN],low[NN];int fi[NN];bool vis[NN*3];int te;int link[NN*5][2];struct query{ int a,b,c,lca;}qu[NN];void init_edge(){ te=-1; memset(fi,-1,sizeof(fi));}void addedge(int fr,int to,int g=0){ ++te;ed[te].ne=fi[fr];fi[fr]=te; ed[te].v=to;ed[te].g=g;}void tarjan(int u){ int tmp,e,v; dfn[u]=low[u]=++totdfn; sta[++top]=u; for(e=fi[u];e!=-1;e=ed[e].ne)if (!vis[e]){ v=ed[e].v; vis[e]=vis[e^1]=1; if (!dfn[v]){ tarjan(v); if (low[v]<low[u]) low[u]=low[v]; if (low[v]>dfn[u]){ totb++; do{ tmp=sta[top--]; block[tmp]=totb; }while(tmp!=v); he.push_back(make_pair(u,v)); } } else if (dfn[v]<low[u]) low[u]=dfn[v]; }}int scc(){ int i,u,v; memset(dfn,0,sizeof(dfn)); totb=top=totdfn=0; memset(vis,0,sizeof(vis)); he.clear(); tarjan(1); if (top){ totb++; do{ i=sta[top--]; block[i]=totb; }while(i!=1); } init_edge(); for(i=0;i<he.size();++i){ u=he[i].first;v=he[i].second; addedge(block[u],block[v],u); addedge(block[v],block[u],v); } return totb;}vector<pii> vec[NN];int set[NN];int findset(int x){return x==set[x]?x:set[x]=findset(set[x]);}void init_lca(int n){ for(int i=1;i<=n;++i){ vec[i].clear();set[i]=i;vis[i]=0; }}void tarjan_lca(int u,int fa){ int e; int v; for(e=fi[u];e!=-1;e=ed[e].ne){ v=ed[e].v; if (v==fa) continue; tarjan_lca(v,u); set[v]=u; } vis[u]=1; for(e=0;e<vec[u].size();++e){ v=vec[u][e].first; if (vis[v]) qu[vec[u][e].second].lca=findset(v); }}struct segtree{ int ls,rs,w;}t[NN*20];int tott;int root[NN];int tn;int build(int l,int r){ int p=++tott; t[p].w=0; if (l==r){t[p].ls=t[p].rs=0;return p;} int m=l+r>>1; t[p].ls=build(l,m); t[p].rs=build(m+1,r); return p;}int insert(int pos,int tl,int tr,int pas){ int p=++tott; t[p]=t[pas]; t[p].w+=1; if (t[p].ls==t[p].rs){ return p; } int m=tl+tr>>1; if (pos<=m) t[p].ls=insert(pos,tl,m,t[p].ls); else t[p].rs=insert(pos,m+1,tr,t[p].rs); return p;}int query(int pos,int tl,int tr,int a,int b,int lca){ if (tl==tr){ return t[a].w+t[b].w-2*t[lca].w; } int m=tl+tr>>1; if (pos<=m){ return query(pos,tl,m,t[a].ls,t[b].ls,t[lca].ls); } else{ return query(pos,m+1,tr,t[a].rs,t[b].rs,t[lca].rs); }}void dfsbuild(int u,int fa){ root[u]=insert(u,1,tn,root[fa]); int e,v; for(e=fi[u];e!=-1;e=ed[e].ne){ v=ed[e].v; if (v==fa) continue; dfsbuild(v,u); }}void dfs(int u,int fa,int bg){ int e,v,lca,tmp; set[u]=-1; for(e=0;e<vec[u].size();++e){ lca=vec[u][e].first; tmp=set[lca]; link[vec[u][e].second][0]=tmp; link[vec[u][e].second][1]=bg; } for(e=fi[u];e!=-1;e=ed[e].ne){ v=ed[e].v; if (v==fa) continue; set[u]=ed[e].g; dfs(v,u,ed[e^1].g); } set[u]=-1;}#define py puts("Yes")#define pn puts("No")int main(){ //freopen("4674in.txt","r",stdin); int n,m,a,b,q,lca,c,i; int ba,bb,bc; while(scanf("%d%d",&n,&m)!=EOF){ init_edge(); for(i=1;i<=m;++i){ scanf("%d%d",&a,&b); addedge(a,b); addedge(b,a); } scanf("%d",&q); for(i=1;i<=q;++i){ scanf("%d%d%d",&a,&b,&c); qu[i].a=a; qu[i].b=b; qu[i].c=c; } tn=scc(); //双连通缩点 init_lca(tn); //求lca for(i=1;i<=q;++i){ a=block[qu[i].a]; b=block[qu[i].b]; vec[a].push_back(make_pair(b,i)); vec[b].push_back(make_pair(a,i)); } tarjan_lca(1,-1); he.clear(); for(i=1;i<=tn;++i) vec[i].clear(); //求每个问题中a、b、c的出点 for(i=1;i<=q;++i){ vec[block[qu[i].a]].push_back(make_pair(qu[i].lca,i)); vec[block[qu[i].b]].push_back(make_pair(qu[i].lca,i+q)); vec[block[qu[i].c]].push_back(make_pair(qu[i].lca,i+q*2)); vec[block[qu[i].a]].push_back(make_pair(block[qu[i].c],i+q*3)); vec[block[qu[i].b]].push_back(make_pair(block[qu[i].c],i+q*4)); } memset(set,-1,sizeof(set)); dfs(1,-1,-1); for(i=1;i<=tn;++i) vec[i].clear(); tott=-1; //建立主席树 root[0]=build(1,tn); dfsbuild(1,0); for(i=1;i<=q;++i){ a=qu[i].a;b=qu[i].b;c=qu[i].c;lca=qu[i].lca; if (c==b||c==a){py;continue;} //排除c==b、c==a if (a==b) {pn;continue;} //排除a==b,这样a、b、c肯定不相等了 ba=block[a];bb=block[b];bc=block[c]; if (lca==bc||query(bc,1,tn,root[ba],root[bb],root[lca])) {//首先必须在缩点后的路径上,再判断不合法的 if (lca==ba&&lca==bb){ //a、b、lca同块 if (bc==lca) py; else pn; } else if (lca==ba){ //a与lca同块 if (bc==lca){ //c与lca同块 if (link[i+q][0]!=a) py; else pn; } else if (bc==bb){ //c与b同块 if (link[i+q][1]!=b) py; else pn; } else { //都不同块,则在b->lca路径上 if (link[i+q*2][1]==c) py; else if (link[i+q*2][1]!=link[i+q*4][0]) py; else pn; } } else if (lca==bb){ //b与lca同块 if (bc==lca){ if (link[i][0]!=b) py; else pn; } else if (bc==ba){ if (link[i][1]!=a) py; else pn; } else { if (link[i+q*2][1]==c) py; else if (link[i+q*2][1]!=link[i+q*3][0]) py; else pn; } } else { //a、b、lca、都不同块 if (bc==lca){ if (link[i][0]!=link[i+q][0]) py; else if (link[i][0]==c) py; else pn; } else if (bc==ba){ if (link[i][1]!=a) py; else pn; } else if (bc==bb){ if (link[i+q][1]!=b) py; else pn; } else { if (link[i+q*2][1]==c) py; else if (link[i+q*3][0]==-1){ if (link[i+q*4][0]!=link[i+q*2][1]) py; else pn; } else { if (link[i+q*3][0]!=link[i+q*2][1]) py; else pn; } } } } else pn; } } return 0;}
0 0
- hdu4674 Trip Advisor,双连通分量,LCA
- hdu 2460(边双连通分量+LCA)
- 【边双连通分量 && LCA】POJ
- 图论-桥/割点/双连通分量/缩点/LCA
- hdu 2460(tarjan求边双连通分量+LCA)
- POJ 3694 双连通分量 割边 LCA
- poj 3694 Network 边双连通分量+LCA
- poj3694Networks(边双连通分量+缩点+LCA)
- 双连通分量
- 双连通分量_road
- 边双连通分量
- 双连通分量
- 双连通分量-tarjan
- 双连通分量
- 双连通分量
- 双连通分量-tarjan
- 双连通分量
- poj3177 双连通分量
- QMake 生成VS2013的工程文件
- 希望能坚持下去
- 如何配置JDK和设置系统默认JDK版本
- 【编程练习】收集的一些c++代码片,算法排序,读文件,写日志,快速求积分等等
- hdu 5093 Battle ships(二分图匹配)
- hdu4674 Trip Advisor,双连通分量,LCA
- eclipse远程调试jetty
- 【iOS7的一些总结】14、Block的概念和应用
- 关闭输出流时Socket的行为(stackoverflow)
- QQ通信协议_概述
- lua基础【三】唯一数据结构table表
- HDU - 2197 本原串
- 奇偶数分离
- 算法分析与设计的读书笔记加个人总结