如何查找图表是否为树?

时间:2014-08-11 00:32:05

标签: algorithm graph depth-first-search

我正在尝试解决SPOJ问题is it a tree ?,我必须检查图表是否为树? 在这个问题中,我使用DFS来检测图表是否有循环..

我的代码是..

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <cstring>
#include <ctime>
#include <string.h>

using namespace std;

typedef long long int64;
typedef unsigned long long uint64;
#define two(X) (1<<(X))
#define twoL(X) (((int64)(1))<<(X))
#define contain(S,X) (((S)&two(X))!=0)
#define containL(S,X) (((S)&twoL(X))!=0)
const double pi=acos(-1.0);
const double eps=1e-11;
template<class T> inline void checkmin(T &a,T b){if(b<a) a=b;}
template<class T> inline void checkmax(T &a,T b){if(b>a) a=b;}
template<class T> inline T sqr(T x){return x*x;}
typedef pair<int,int> ipair;
#define SIZE(A) ((int)A.size())
#define LENGTH(A) ((int)A.length())
#define MP(A,B) make_pair(A,B)
#define PB(X) push_back(X)
int scanInt()
{
    char c;
    int ans=0;
    while(true)
    {
        c=getchar_unlocked();
        if(c==' ' || c=='\n')
            return ans;
        ans=(ans<<3)+(ans<<1)+c-'0';
    }
}
bool applyDFS(vector<vector<int> > &graph,int n)
{
    queue <int> st;
    int i,j=0;
    vector<bool> visited(n+1,false);
    int node=1;
    st.push(1);
    while(!st.empty())
    {
        node=st.front();
        st.pop();
        if(visited[node])
           {
            return false;
            }
            visited[node]=true;
        for(i=0;i<graph[node].size();i++)
            {
                if(!visited[graph[node][i]])
                    st.push(graph[node][i]);
            }
        j++;
    }
    return j==n?true:false;
}
int main()
{
    int n,m,x,y,i;
    //freopen("input.txt","r",stdin);
    n=scanInt();
    m=scanInt();
       vector <vector<int> > graph(n+1);
       stack <int > st;
    for(i=0;i<m;i++)
    {
          x=scanInt();
          y=scanInt();
          graph[x].PB(y);
          graph[y].PB(x);
          st.push(x);
    }
    if(applyDFS(graph,n))
        cout<<"YES\n";
    else
        cout<<"NO\n";
    return 0;
}

当我提交解决方案时,我收到了“超出时间限制”的消息。有没有更好的方法来解决这个问题?

1 个答案:

答案 0 :(得分:4)

正如kevmo314在他的评论中所提到的,我们需要检查图表的连接性,边缘的数量正好是n-1,以确保图形是树。

所以有两个观察结果:

  • 如果边数为n - 1,我们只需要检查连接性。

  • 使用disjoint set解决此问题,因为每个边缘(如果是树),此边缘应连接两个断开连接的组件,否则,此图形不是树。因此,时间复杂度为O(n),因为只有n - 1边缘需要检查。