印刷欧拉路径

时间:2014-07-08 19:51:40

标签: c++ algorithm graph

我得到了一个无向图,我需要打印从顶点A到顶点B的这个图的euler路径。我的算法是这样的:首先,我通过使用Tarjan算法找到所有的桥边。然后,从顶点A开始,从每个顶点我选择他的一条边,尝试不烧桥,也就是说我可以选择不是我选择它们的桥的边。然而,这个解决方案给了我30/100分的问题。我发现O((N + M)^ 2)解决方案工作正常,但由于N和M非常大,我需要线性的东西。

这是我的代码,你有什么建议吗? :

int N, M, A, B, c, dfs_low[MAX_N], dfs_num[MAX_N], dfs_parent[MAX_N],articulation_vertex[MAX_N];
int dfsNumberCounter = 1, dfsRoot, rootChildren;
vii g[MAX_N];

void articulationPointAndBridge(int u) {
  dfs_low[u] = dfs_num[u] = dfsNumberCounter++;     // dfs_low[u] <= dfs_num[u]
  for (int j = 0; j < (int)g[u].size(); j++) {
    ii v = g[u][j];
    if (dfs_num[v.first] == DFS_WHITE) {                          // a tree edge
      dfs_parent[v.first] = u;
      if (u == dfsRoot) rootChildren++;  // special case, count children of root
      articulationPointAndBridge(v.first);
      if (dfs_low[v.first] > dfs_num[u]){                           // for bridge
        g[u][j].second = 2;
        for(int i=0;i<g[v.first].size();i++)
            if(g[v.first][i].first == u && g[v.first][i].second){
                g[v.first][i].second = 2;
                break;
            }
       }
      dfs_low[u] = min(dfs_low[u], dfs_low[v.first]);       // update dfs_low[u]
    }
    else if (v.first != dfs_parent[u])       // a back edge and not direct cycle
      dfs_low[u] = min(dfs_low[u], dfs_num[v.first]);       // update dfs_low[u]
} }

void EulPath(int u){ 
    int idx = -1;
    for(int i=0;i<g[u].size();i++)
        if(g[u][i].second == 1){
            idx = i;
            break;
        }

    if(idx == -1)
        for(int j=0;j<g[u].size();j++)
            if(g[u][j].second){
                idx = j;
                break;
            }
    if(idx != -1){
        int v = g[u][idx].first;
        out<<u+1<<" "<<v+1<<endl;
        g[u][idx].second=0;
        for(int j=0;j<g[v].size();j++)
            if(g[v][j].first == u && g[v][j].second){
                g[v][j].second = 0;
                break;
            }
        EulPath(v);
    }

}





int main() {
    //in = fopen("input.txt","r"); out = fopen("output.txt","w");
    in.open("input.txt"); out.open("output.txt");

    //fscanf(in, "%d %d %d %d" , &N, &M, &A, &B);
    in>>N>>M>>A>>B;
    for(int i=0;i<M;i++){
        int t,t2;
        //fscanf(in, "%d %d", &t, &t2);
        in>>t>>t2; t--; t2--;
        g[t].pb(ii(t2,1));
        g[t2].pb(ii(t,1));
    }
    articulationPointAndBridge(A-1);
    /*for(int i=0;i<N;i++)
        for(int j=0;j<g[i].size();j++)
            cout << i <<" "<<g[i][j].first<<" "<<g[i][j].second<<endl;
            cin>>N;*/
    EulPath(A-1);

    in.close(); out.close();
    //fclose(in); fclose(out);
    return 0;
}

1 个答案:

答案 0 :(得分:2)

我会考虑实施Hierholzer的算法。 (参见,例如http://en.wikipedia.org/wiki/Eulerian_path#Hierholzer.27s_algorithm)。无需预先检测桥梁。