有向图的欧拉回路判定问题 poj1386

这个题也卡卡卡,发现自己好粗心,唉.。

有向图的判定:

统计每个点的出度和入度,

前提是有向图是连通图。
1. 如果每个点的出度 = 入度 则存在欧拉回路。
2. 如果有且仅有两点出度、入度不想等,且这两个点的出度 - 入度差为1 或 -1.差为1的那个点是欧拉图的起点,为 -1 的是重点。

这个题先来判断图的连通性,用并查集的方法,值得注意的一点是并查集是以点为元素的,所以要开26长度的数组。
在接下来就是判断出度和入度了。

#include
#include
#include
#include
#include
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;
}

你可能感兴趣的:(图论及其应用)