码迷,mamicode.com
首页 > 其他好文 > 详细

codeforces 652E Pursuit For Artifacts 边双连通分量

时间:2016-03-27 19:26:31      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:

题意:n个点,m条边的无向图,有的边上有标记,每条边只能走一次

        给你一个起点,一个终点,询问是否能找到从起点到终点的路径,这条路径至少包含一条含有标记的边

分析:然后边双缩点

下面介绍一下边双的性质

1,删掉边双内任意一条边,不影响边双的连通性

2,任取边双内两个点u,v,对于边双里面的任意一条边,至少包含于一条u到v的路径

 

所以对于这个题,可以运用上述的第二个性质,对于在边双里的标记边,都是可以经过的

然后缩点以后,变成一棵树,然后从起点所在的边双开始遍历,找到到终点所在边双的路径,询问权值是否大于0就行了

注意一点:这里的权值是点权加边权

技术分享
#include <iostream>
#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;
const int N=3e5+5;
int n,m,s,t;
struct Edge
{
    int u,v,w,next;
} edge[N<<1],e[N<<1];
int head[N],tot,h[N];
void add(int u,int v,int w)
{
    edge[tot].u=u;
    edge[tot].v=v;
    edge[tot].w=w;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void adde(int u,int v,int w)
{
    e[tot].v=v;
    e[tot].w=w;
    e[tot].next=h[u];
    h[u]=tot++;
}
int pre[N],low[N],clk,bcc,bel[N];
stack<int>S;
void targin(int u,int f)
{
    pre[u]=low[u]=++clk;
    S.push(u);
    for(int i=head[u]; ~i; i=edge[i].next)
    {
        int v=edge[i].v;
        if(v==f)continue;
        if(!pre[v])
        {
            targin(v,u);
            low[u]=min(low[v],low[u]);
        }
        else low[u]=min(pre[v],low[u]);
    }
    if(pre[u]==low[u])
    {
        ++bcc;
        int k;
        do
        {
            k=S.top();
            S.pop();
            bel[k]=bcc;
        }
        while(k!=u);
    }
}
int val[N];
bool get(int u,int f,int sum)
{
    sum+=val[u];
    if(u==t)return sum;
    for(int i=h[u]; ~i; i=e[i].next)
    {
        int v=e[i].v;
        if(v==f)continue;
        if(get(v,u,sum+e[i].w))return true;
    }
    return false;
}
int main()
{
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof(head));
    int tmp=0;
    for(int i=1; i<=m; ++i)
    {
        int u,v,w;
        scanf("%d%d%d",&u,&v,&w),tmp+=w;
        add(u,v,w),add(v,u,w);
    }
    scanf("%d%d",&s,&t);
    if(tmp==0)
    {
        printf("NO\n");
        return 0;
    }
    targin(s,-1);
    tmp=tot;
    memset(h,-1,sizeof(h)),tot=0;
    for(int i=0; i<tmp; i=i+2)
    {
        int u=edge[i].u,v=edge[i].v;
        u=bel[u],v=bel[v];
        if(u==v)val[u]+=edge[i].w;
        else adde(u,v,edge[i].w),adde(v,u,edge[i].w);
    }
    s=bel[s];
    t=bel[t];
    if(get(s,-1,0))printf("YES\n");
    else printf("NO\n");
    return 0;
}
View Code

 

 

 

       

codeforces 652E Pursuit For Artifacts 边双连通分量

标签:

原文地址:http://www.cnblogs.com/shuguangzw/p/5326435.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!