• Codeforces 521 E cycling city


    cf的一道题,非常有意思,题目是问图中是否存在两个点,使得这两个点之间有三条路径,而且三条路径没有公共点。

    其实就是判断一下是否为仙人掌就行了,如果不是仙人掌的话肯定就存在,题目难在输出路径上,改了半天也不对,借鉴了一个dalao的代码。感觉非常神奇。

    首先是判断是否为仙人掌,利用返祖边即可,如果一条树边被两条或者以上的返祖边覆盖,那么图就肯定不是一个仙人掌,利用差分可以实现。

    然后是输出路径,找到一个被覆盖了两次的边,那么两条返祖边一定跨过了这个边,往上往下搜索就行了,找到了两条返祖边。那么路径就出来了,一条毫无疑问是树边,一直网上蹦就行了。

    另外两个就是返祖边,那么问题来了,起点在哪?因为路径不能有交点(我们设深度小的为起点,深度大的为终点),那么终点一定是两条返祖边的下面端点的lca(这样很明显两个通过返祖边走上去的路径没有交点,而且这两条路径不会沿着树边往上走,他们可以往下走然后沿着非树边跳上去到起点,这样就不会和树边那条路径有交点了),起点就是两条返祖边上面端点中比较深的一个点,因为如果是比较浅的那个点的话,会和树边上的路径有交点。

    那么我们就做完了,附上代码。——by VANE

    #include<bits/stdc++.h>
    using namespace std;
    const int N=200005;
    int dep[N],fa[N],f[N];
    int n,m,l1,l2,r1,r2,s,t,x,y;
    vector<int> e[N];
    void dfs(int x,int father)
    {
        dep[x]=dep[father]+1;
        fa[x]=father;
        for(int i=0;i<e[x].size();++i)
        if(!dep[e[x][i]]) dfs(e[x][i],x);
        else if(dep[e[x][i]]<dep[x]&&e[x][i]!=father)
        --f[e[x][i]],++f[x];
        f[father]+=f[x];
    }
    void DFS(int x)
    {
        for(int i=0;i<e[x].size();++i)
        if(dep[e[x][i]]==dep[x]+1)
        {
            DFS(e[x][i]);
            if(l2) return;
        }
        else if(dep[e[x][i]]<dep[s]&&e[x][i]!=fa[x])
        {
            if(l1) r2=x,l2=e[x][i];
            else r1=x,l1=e[x][i];
            if(l2) return;
        }
    }
    int d[N];
    void go(int l,int r)
    {
        int k=t;t+=abs(dep[r]-dep[l])+1;
        if(dep[l]>dep[r])
        for(int i=l,j=k+1;j<=t;i=fa[i],++j) d[j]=i;
        else
        for(int i=r,j=t;j>k;i=fa[i],--j) d[j]=i;
    }
    void print()
    {
        printf("%d ",t);
        for(int i=1;i<=t;++i) printf("%d ",d[i]);puts("");
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;++i)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            e[a].push_back(b);
            e[b].push_back(a);
        }
        for(int i=1;i<=n;++i) if(!dep[i]) dfs(i,0);
        for(int i=1;i<=n;++i)
        if(f[i]>1) {s=i;break;}
        if(!s) {puts("NO");return 0;}
        DFS(s);
        puts("YES");
        if(dep[l1]>dep[l2]) swap(l1,l2),swap(r1,r2);
        for(x=r1,y=r2;x!=y;)
        dep[x]>dep[y]?x=fa[x]:y=fa[y];
        t=0;go(x,r1);go(l1,l2);print();
        t=0;go(x,r2);go(l2,l2);print();
        t=0;go(x,l2);print();
        return 0;
    }
  • 相关阅读:
    C语言移动一个点
    C语言数据结构无向图
    C语言学生管理系统(C语言课程设计/精简版)
    C语言贪吃蛇
    2017蓝桥杯九宫幻方(C++B组)
    2017蓝桥杯Excel地址(C++C组)
    2017蓝桥杯杨辉三角(C++C组)
    2017蓝桥杯算式900(C++C组)
    2017蓝桥杯兴趣小组(C++C组)
    javascript 的默认对象
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8029865.html
Copyright © 2020-2023  润新知