有向圖的歐拉回路判定問題 poj1386

這個題也卡卡卡,發現自己好粗心,唉.。

有向圖的判定:

統計每個點的出度和入度,

前提是有向圖是連通圖。
1. 如果每個點的出度 = 入度 則存在歐拉回路。
2. 如果有且僅有兩點出度、入度不想等,且這兩個點的出度 - 入度差爲1 或 -1.差爲1的那個點是歐拉圖的起點,爲 -1 的是重點。

這個題先來判斷圖的連通性,用並查集的方法,值得注意的一點是並查集是以點爲元素的,所以要開26長度的數組。
在接下來就是判斷出度和入度了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<cmath>
using namespace std;
const int MAXN = 1e5 + 10;
int father[30]; 
int _rank[30];
int d1[30]; // 出度
int d2[30]; // 入度
bool h[MAXN]; // 判斷是否出現邊中
void init()
{
    for(int i = 1;i <= 26;++i)
    {
        father[i] = i;
        _rank[i] = 0;
    }
    return ;
}
int _find(int i)
{
    int root = i;
    int temp = i;
    while(father[root] != root)
    {
        root = father[root];
    }
    while(father[temp] != root)
    {
        int t;
        t = father[temp];
        father[temp] = root;
        temp = t;
    }
    return root;
}
void _union(int x,int y)
{
    int root1 = _find(x);
    int root2 = _find(y);
    if(root1 != root2)
    {
        if(_rank[root1] > _rank[root2])
        {
            father[root2] = root1;
        }
        else
        {
            father[root1] = root2;
            if(_rank[root1] == _rank[root2])
            {
                _rank[root2]++;
            }
        }
    }
    return;
}
struct Edge
{
    int u,v;
};
Edge e[MAXN];
int n;
bool tell() // 判斷連通性
{
    init();
    for(int i = 1;i <= n;++i) // 先進行一邊合併
    { 
        int u = e[i].u;
        int v = e[i].v;
        if(_find(u) != _find(v))
        {
            _union(u,v);
        }
    }
    bool flag = 1;
    int l= -1;
    for(int i = 1;i <= 26;++i) // 在判斷father數組是否只有一個父親節點
    {
      if(h[i]) // 將不存在點排除
      {
          if(l == -1)
          {
              l = father[i];
          }
          else
          {
              if(father[i] != father[l])
              {
                  flag = 0;
              }
          }
      }
    }
    return flag;
}
int main()
{
    int T;

    cin >> T;

    while(T--)
    {
        memset(d1,0,sizeof(d1));
        memset(d2,0,sizeof(d2));
        memset(h,0,sizeof(h));
        cin >> n;
        string s;
        for(int i = 1; i <= n;++i)
        {
            cin >> s;
            e[i].u = s[0] - 'a' + 1;
            e[i].v = s[s.size() - 1] - 'a' + 1;
            d1[e[i].u]++;
            d2[e[i].v]++;
            h[e[i].u] = 1;
            h[e[i].v] = 1;
        }
        bool flag = tell();
        int a,b,k = 0,t = 0;
        if(flag)
        {
            for(int i = 1;i <= 26;++i)
            {
                if(d1[i] != d2[i])
                {
                    t = 1;
                    k++;
                    if(k == 1)
                    {
                       a = i;
                    }
                    if(k == 2)
                    {
                        b = i;
                    }
                }
            }
            if(!t)
                cout << "Ordering is possible." << endl;
            else
            {
                if(k == 2)
                {
                    if((int )abs(d1[a] - d2[a]) == 1 && (int )abs(d1[b] - d2[b]) == 1)
                    {
                        cout << "Ordering is possible." << endl;
                    }
                    else
                    {
                        cout << "The door cannot be opened." << endl;
                    }
                }
                else
                {
                    cout << "The door cannot be opened." << endl;
                }
            }
        }
        else
        {
            cout << "The door cannot be opened." << endl;
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章