【C++】「2010 ACM-ICPC Multi-University Training Contest」「Nada Open 2002」Cactus

【来源】

2010 ACM-ICPC Multi-University Training Contest(16)——Host by NUDT
Nada Open 2002
HDU-3594
UVA-10510
Kattis-cactus
vjudge

以上题库题目大意相同,但题目描述、输入格式不同,代码以HDU为准。

【题目描述】

1.It is a Strongly Connected graph.
2.Each edge of the graph belongs to a circle and only belongs to one circle.
We call this graph as CACTUS.

1.这是一个强连通图。
2.图形的每个边都属于一个圆,并且仅属于一个圆。
我们称此图为仙人掌图。
在这里插入图片描述

There is an example as the figure above. The left one is a cactus, but the right one isn’t. Because the edge (0, 1) in the right graph belongs to two circles as (0, 1, 3) and (0, 1, 2, 3).

上图有一个例子。左边的是仙人掌图,而右边的不是。因为右图中的边(0,1)属于两个圆,分别为(0,1,3)和(0,1,2,3)。

【输入格式】

The input consists of several test cases. The first line contains an integer T (1<=T<=10), representing the number of test cases.
For each case, the first line contains a integer n (1<=n<=20000), representing the number of points.
The following lines, each line has two numbers a and b, representing a single-way edge (a->b). Each case ends with (0 0).
Notice: The total number of edges does not exceed 50000.

输入包含几个测试用例。第一行包含一个整数T(1 <= T <= 10),代表测试用例的数量。
对于每种情况,第一行都包含一个整数n(1 <= n <= 20000),代表点数。
在以下几行中,每行都有两个数字a和b,分别表示单向边缘(a-> b)。每种情况都以(0 0)结尾。
注意:边的总数不超过50000。

【输出格式】

For each case, output a line contains “YES” or “NO”, representing whether this graph is a cactus or not.

对于每种情况,输出的行均包含“是”或“否”,代表该图是否为仙人掌。

【样例输入】

2
4
0 1
1 2
2 0
2 3
3 2
0 0
4
0 1
1 2
2 3
3 0
1 3
0 0

【样例输出】

YES
NO

【解析】

解题思路:

1.首先得先熟练掌握tarjan算法的应用。
2.必须了解仙人掌图的三个性质:
(1)仙人掌dfs图中不能有横向边,简单的理解为每个点只能出现在一个强联通分量中。
(2)low[v]<dfn[u],其中u为v的父节点
(3)a[u]+b[u]<2, a[u]为u节点的儿子节点中有a[u]个low值小于u的dfn值。b[u]为u的逆向边条数。

三个性质有一个不满足则不是仙人掌图。

【代码】

#pragma GCC optimize(3,"Ofast","inline")

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;

const int N=5e5;
const int inf=1e9;

struct Node {
    int to,nt;
} e[N];

int n,m,cnt,tot,num,top,index,flag;
int h[N],fa[N],dfn[N],low[N],instack[N],stap[N],belong[N],vis[N];

inline void add(int x,int y) {
    e[cnt].to=y;
    e[cnt].nt=h[x];
    h[x]=cnt++;
}

void tarjan(int u) {
    int v;
    dfn[u]=low[u]=++index;
    instack[u]=1;
    stap[++top]=u;
    for(int i=h[u]; i!=-1; i=e[i].nt) {
        v=e[i].to;
        if(!dfn[v]) {
            fa[v]=u;
            tarjan(v);
            if(low[u]>low[v]) low[u]=low[v];
        } else if(instack[v]) {
            if(dfn[v]<low[u]) low[u]=dfn[v];
            int tmp=u;
            while(v!=fa[tmp]) {
                vis[tmp]++;
                if(vis[tmp]>1) {
                    flag=1;
                    return;
                }
                tmp=fa[tmp];
            }
        }
    }
    if(low[u]==dfn[u]) {
        tot++;
        do {
            v=stap[--top];
            instack[v]=0;
            belong[v]=tot;
        } while(v!=u);
    }
}

int main() {
    int T;
    scanf("%d",&T);
    while(T--) {
        tot=top=index=flag=0;
        memset(h,-1,sizeof(h));
        memset(fa,0,sizeof(fa));
        memset(dfn,0,sizeof(dfn));
        memset(instack,0,sizeof(instack));
        memset(vis,0,sizeof(vis));
        int n;
        scanf("%d",&n);
        while(1) {
            int x,y;
            scanf("%d%d",&x,&y);
            if(x==0 && y==0) break;
            add(x+1,y+1);
        }
        for(int i=1; i<=n; i++) {
            if(!dfn[i]) tarjan(i);
        }
        if(tot>1 || flag) {
            puts("NO");
        } else puts("YES");
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ACM-ICPC(国际大学生程序设计竞赛)是一项面向大学生的计算机编程竞赛,涉及算法和数据结构等领域。在比赛中,选手需要解决一系列编程问题,使用合适的算法和数据结构来实现正确和高效的解决方案。 对于整理ACM-ICPC模板,以下是一些建议: 1. 了解比赛要求:首先,你需要了解ACM-ICPC比赛的具体要求和规则。这包括了解比赛所涉及的算法和数据结构,以及题目的类型和难度等。 2. 收集资料:收集与ACM-ICPC相关的资料,包括经典算法和数据结构的实现代码、常见问题的解题思路等。可以参考教材、博客、论文等资源。 3. 整理模板:将收集到的资料整理成模板。可以按照算法和数据结构的分类进行整理,例如排序算法、图算法、字符串算法等。对每个模板,添加必要的注释和示例代码,以便理解和使用。 4. 测试代码:对每个模板编写测试代码,确保它们的正确性和可靠性。可以使用已知的测试用例或自行设计测试用例。 5. 更新与扩充:定期更新和扩充模板,以适应ACM-ICPC比赛中新出现的算法和数据结构。同时,根据自己的经验和理解,对模板进行优化和改进。 6. 练习和复习:在比赛之前,利用整理好的模板进行练习和复习。尝试解决一些经典问题,使用模板中的算法和数据结构进行实现,并进行优化。 希望这些建议对你整理ACM-ICPC模板有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值