您的位置:首页 > 其它

codeforces 652E

2016-03-26 09:20 316 查看

题目大意

给你一个nn个点,mm条边的连通图,某些边上会有宝藏,只有一个询问,问从aa到bb是否存在一条路径使得,路径上没有重边并且路径上有宝藏。

范围

(1 ≤ n ≤ 3∗105,0 ≤ m ≤ 3∗105)(1 ≤ n ≤ 3*10^5, 0 ≤ m ≤ 3*10^5)

思路

易得,如果一个环上有宝藏,那么我一定可以从环上的一个点进去,拿到宝藏,然后从任意一个点出来。那么我就可以缩环,建树,现在的树就是一颗某些点有宝藏,某些边有宝藏了,那我就求一下aa到bb的树上路径是否有宝藏就行了。

参考代码

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
#define maxn 600005
#define maxsq 30
using namespace std;

int n,m,S,T;

int head[maxn],t[maxn * 2],vv[maxn * 2],next[maxn * 2],sum;

void insert(int x,int y,int z){
t[++sum]=y;
next[sum]=head[x];
vv[sum]=z;
head[x]=sum;
}

int dfn[maxn],low[maxn],scc,cnt;

int instack[maxn],sta[maxn],top,belong[maxn];

int fr[maxn],ok[maxn];

int head2[maxn],t2[2*maxn],next2[2*maxn],sum2,v2[maxn*2];

void insert2(int x,int y,int z){
t2[++sum2]=y;
next2[sum2]=head2[x];
v2[sum2]=z;
head2[x]=sum2;
}

void Tarjan(int u,int fa)
{
int i,v;
low[u]=dfn[u]=++cnt;
sta[++top]=u;
instack[u]=1;
for(i=head[u];i;i=next[i])
{
v=t[i];
if(i==(fa^1))
continue;
if(!dfn[v])
{
fr[v]=i;
Tarjan(v,i);
low[u]=min(low[u],low[v]);
}
else if(instack[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
scc++;
while(1)
{
v=sta[top--];
instack[v]=0;
belong[v]=scc;
if(v==u)
break;
}
}
}

int fa[maxn][maxsq][2],deep[maxn];

void maketree(int x,int father){
deep[x]=deep[father]+1;
for(int tmp=head2[x];tmp;tmp=next2[tmp]) {
if (t2[tmp]==father) continue;
fa[t2[tmp]][0][0]=x;
fa[t2[tmp]][0][1]=(ok[x]) || (ok[t2[tmp]]) || (v2[tmp]);
maketree(t2[tmp],x);
}
}

bool getlca(int x,int y){
if (deep[x]<deep[y]) swap(x,y);
fd(i,20,0)
if (deep[fa[x][i][0]]>=deep[y]) {
if (fa[x][i][1]) return 1;
x=fa[x][i][0];
}
if (x==y) return 0;
fd(i,20,0)
if (fa[x][i][0]!=fa[y][i][0]) {
if (fa[x][i][1]) return 1;
if (fa[y][i][1]) return 1;
x=fa[x][i][0];
y=fa[y][i][0];
}
if (fa[x][0][1]) return 1;
if (fa[y][0][1]) return 1;
return 0;
}

int main(){
sum=1;
scanf("%d%d",&n,&m);
fo(i,1,m) {
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
insert(x,y,z);
insert(y,x,z);
}
fo(i,1,n)
if (dfn[i]==0) Tarjan(i,0);
fo(i,1,n) {
for(int tmp=head[i];tmp;tmp=next[tmp]) {
if (belong[t[tmp]]==belong[i]) {
if (vv[tmp]) ok[belong[i]]=1;
continue;
}
insert2(belong[i],belong[t[tmp]],vv[tmp]);
}
}
maketree(1,0);
fa[1][0][0]=1;
fa[1][0][1]=ok[1];
fo(i,1,20)
fo(j,1,scc) fa[j][i][0]=fa[fa[j][i-1][0]][i-1][0],fa[j][i][1]=fa[j][i-1][1] || fa[fa[j][i-1][0]][i-1][1];
scanf("%d%d",&S,&T);
if (ok[belong[S]]||ok[belong[T]]) {
puts("YES");
return 0;
}
if (getlca(belong[S],belong[T])) {
puts("YES");
} else puts("NO");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: