Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
Total Submission(s): 955    Accepted Submission(s): 284

Problem Description
Ery is interested in graph theory, today he ask BrotherK a problem about it: Given you a undirected graph with X can't be 0)
 
Input
The first line contains a single integer i

There is at most one edge between any pair of vertex.

 

Output
For each test, print two lines.

The first line contains "YES" or "NO" for question 1. 

The second line contains "YES" or "NO" for question 2.
 
Sample Input
3 1 0 3 3 1 2 2 3 3 1 4 4 1 2 2 3 3 4 4 1
 
Sample Output
NO NO YES NO NO YES
Hint
If you need a larger stack size, please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.
 
Source
 
Recommend
hujie   |   We have carefully selected several similar problems for you:  6253 6252 6251 6250 6249 
大致题意:给定一个图,问是否存在奇环和偶环.
分析:是否有奇环非常简单,判断一下是不是二分图就可以了.对于偶环的话,题目给的是无向图,无向图上考虑环就先建出dfs树来,找返祖边,如果返祖点到目前点的深度差为奇数,那么环就是偶环,直接就判断完了.如果有多个奇环之间共边,那么就存在偶环.而奇环共边就构成了双连通分量,也就是说要先找到双连通分量,然后在每个双连通分量里找奇环,如果奇环的个数>1,那么就存在偶环.
          那么如何找双连通分量?把桥给找出来,桥是一定不在双连通分量里的,因为双连通分量里的任何一条边拿走,其中的点还是连通的,那么不是桥的边就属于双连通分量了.利用tarjan算法找桥.因为是无向图,还要多传递一个参数:父亲节点,并且返祖的时候还要看看终点与起点的深度差.对于每一个点,求出通向它的那条边是谁,反向边就可以通过^1来得到.这样一旦pre[u] = low[u],那么一开始通向u的边就是桥.
          无向图的tarjan算法要注意传递父亲节点这个信息.一个技巧:为了准确快速地获得通向当前点u的边在邻接表中的编号以及反向边的编号,可以将head初始化为-1,tot初始化为2.这样^1就是反向边了.
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stack>
#include <algorithm>

using namespace std;

const int maxn = 600010;

int n, m, T, head[maxn], to[maxn], nextt[maxn], tot, id[maxn], pre[maxn], low[maxn], scc[maxn], scc_tot;
int ans1, ans2, dfs_clock, bridge[maxn], now[maxn], vis[maxn], deep[maxn], f[maxn], sum;
stack <int> s;

void init()
{
    memset(head, -1, sizeof(head));
    memset(id, 0, sizeof(id));
    memset(vis, 0, sizeof(vis));
    memset(now, 0, sizeof(now));
    memset(pre, 0, sizeof(pre));
    memset(low, 0, sizeof(low));
    memset(f, 0, sizeof(f));
    memset(deep, 0, sizeof(deep));
    memset(scc, 0, sizeof(scc));
    memset(bridge, 0, sizeof(bridge));
    sum = 0;
    scc_tot = 0;
    tot = 2;
    ans1 = ans2 = 0;
    dfs_clock = 0;
}

void add(int x, int y)
{
    to[tot] = y;
    nextt[tot] = head[x];
    head[x] = tot++;
}

void tarjan(int u, int fa)
{
    pre[u] = low[u] = ++dfs_clock;
    s.push(u);
    for (int i = head[u]; i != -1; i = nextt[i])
    {
        int v = to[i];
        if (!pre[v])
        {
            id[v] = (i ^ 1);
            tarjan(v, u);
            low[u] = min(low[u], low[v]);
        }
        else
            if (v != fa && pre[v] < pre[u])
                low[u] = min(low[u], pre[v]);
    }
    if (pre[u] == low[u])
    {
        bridge[id[u]] = bridge[id[u] ^ 1] = 1;
        while (1)
        {
            int t = s.top();
            s.pop();
            if (t == u)
                break;
        }
    }
}

void dfs(int u, int depth,int fa)
{
    deep[u] = depth;
    vis[u] = now[u] = 1;
    for (int i = head[u]; i != -1; i = nextt[i])
    {
        if (bridge[i])
            continue;
        int v = to[i];
        if (!vis[v])
            dfs(v, depth + 1,u);
        else
            if (now[v] && v != fa)
            {
                int temp = depth - deep[v] + 1;
                if (temp % 2 == 1)
                {
                    ans1 = 1;
                    sum++;
                    if (sum > 1)
                        ans2 = 1;
                }
                else
                    ans2 = 1;
            }
    }
    now[u] = 0;
}

int main()
{
    scanf("%d", &T);
    while (T--)
    {
        init();
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= m; i++)
        {
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v);
            add(v, u);
        }
        for (int i = 1; i <= n; i++)
            if (!pre[i])
                tarjan(i, 0);
        for (int i = 1; i <= n; i++)
            if (!vis[i])
            {
                sum = 0;
                dfs(i, 1,0);
            }
        printf("%s\n", ans1 ? "YES" : "NO");
        printf("%s\n", ans2 ? "YES" : "NO");
    }

    return 0;
}

 

相关文章:

  • 2021-06-09
  • 2022-12-23
  • 2022-12-23
  • 2021-05-21
  • 2021-06-23
  • 2022-01-09
  • 2021-09-23
猜你喜欢
  • 2021-10-25
  • 2022-01-10
  • 2021-11-09
  • 2021-07-31
  • 2021-12-23
  • 2022-03-04
相关资源
相似解决方案