转载请注明出处:
http://www.cnblogs.com/hzoi-wangxh/p/7738614.html
题解:
求原图的边双。
缩点重建图时,如果z[i]为1且两个端点在一个连通块内,连通块的值设为1,如果不在,边权为1.
缩点之后我们得到的是一棵树,所以只需要从起点向终点跑一个dfs,最后检验终点权值是否为0。
附上代码:
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
#define mmin(a,b) (a<b?a:b)
#define mmax(a,b) (a>b?a:b)
struct tree{
int u,v,next,d;
}l[601000];
struct tree2{
int u,v,next,d;
}l2[601000];
int n,m,lian[301000],e,d[301000],cnt,dis[301000];
int fa[301000],dfn[301000],low[301000],num;
int st[301000],head,be,en;
bool pd[301000];
void bian(int,int,int);
void tar(int,int);
void bian2(int,int,int);
void dfs(int,int);
int main()
{
// freopen("in.txt","r",stdin);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
bian(x,y,z);
bian(y,x,z);
}
for(int i=1;i<=n;i++)
if(dfn[i]==0)
tar(i,0);
memset(lian,0,sizeof(lian));
int cc=e;
e=0;
for(int i=1;i<=cc;i++)
{
int u=fa[l[i].u],v=fa[l[i].v];
if(u==v)
d[u]=mmax(l[i].d,d[u]);
else
bian2(u,v,l[i].d);
}
scanf("%d%d",&be,&en);
dis[fa[be]]=d[fa[be]];
dfs(fa[be],fa[be]);
if(dis[fa[en]]==0) printf("NO");
else printf("YES");
// while(1);
return 0;
}
void bian(int x,int y,int z)
{
e++;
l[e].u=x;
l[e].v=y;
l[e].d=z;
l[e].next=lian[x];
lian[x]=e;
}
void tar(int x,int y)
{
dfn[x]=low[x]=++num;
st[++head]=x;
pd[x]=1;
for(int i=lian[x];i;i=l[i].next)
{
int v=l[i].v;
if(v==y) continue;
if(dfn[v]==0)
{
tar(v,x);
low[x]=mmin(low[x],low[v]);
}
else
if(pd[v]==1)
low[x]=mmin(dfn[v],low[x]);
}
if(dfn[x]==low[x])
{
int temp;
cnt++;
while(1)
{
temp=st[head];head--;
pd[temp]=0;
fa[temp]=cnt;
if(temp==x) break;
}
}
}
void bian2(int x,int y,int z)
{
e++;
l2[e].u=x;
l2[e].v=y;
l2[e].d=z;
l2[e].next=lian[x];
lian[x]=e;
}
void dfs(int x,int y)
{
for(int i=lian[x];i;i=l2[i].next)
{
int v=l2[i].v;
if(v==y) continue;
dis[v]=dis[x]+d[v]+l2[i].d;
dfs(v,x);
}
}