拓扑排序

一、拓扑排序

 1、hdu 1285 确定比赛名次

代码;(领接矩阵 避免 重复)

#include <cstdio>

#include <queue>

#include <vector>

#include <cstring>

#define MAXN 550

using namespace std;

int nVertex, nEdge;

int edge[MAXN][MAXN];

int inDeg[MAXN];

void topOrder(){


    priority_queue<int, vector<int>, greater<int> >que;

    for(int i = 1; i <= nVertex; i++){

        if(inDeg[i] == 0)

            que.push(i);

    }


    int flag = 0;

    while(!que.empty()){


        int front = que.top();

        que.pop();

        if(flag) printf(" ");

        printf("%d", front);

        flag = 1;

        for(int i = 1; i <= nVertex; i++){

            if(edge[front][i] == 0)

                continue;

            inDeg[i] -= edge[front][i];

            if(inDeg[i] == 0)

                que.push(i);

        }

    }

}

int main(){

    while(scanf("%d %d", &nVertex, &nEdge) != EOF){

        memset(edge, 0, sizeof(edge));

        memset(inDeg, 0, sizeof(inDeg));

        for(int i = 0; i < nEdge; i++){

            int a, b;

            scanf("%d %d", &a, &b);


            //重复边多加了 入度 后面会一起 减掉

            edge[a][b]++;

            inDeg[b]++;

        }

        topOrder();

        printf("\n");

    }

    return 0;

}

2、poj 1270 (dfs拓扑排序 输出所有情况 按照字典序大小)

代码:

#include <cstdio>

#include <queue>

#include <vector>

#include <cstring>

#include <iostream>

#define MAXN 550

using namespace std;

/*

a b c

a b c b

*/

int nVertex, nEdge;

int len;

char str[MAXN];

char str2[MAXN];

int nums[MAXN];  //所有字母

vector<int > edges[MAXN];  

int degree[MAXN];

bool vis [MAXN];

vector<int > v;

void Init(){

    v.clear();

    memset(edges,0,sizeof(edges));

    memset(degree,0,sizeof(degree));

}

void dfs(int cnt){


    if(cnt > len) return;


    if(cnt == len){


        for(int i =0;i<len ;i++){


            cout << char(v[i]+'a'-1) <<' ';

        }

        cout << endl;

        return;

    }


    for(int i =0;i<len;i++){


        if(!vis[nums[i]] && !degree[nums[i]]){


            vis[nums[i]] = true;


            for(int j =0;j<edges[nums[i]].size();j++){

                degree[edges[nums[i]][j]]--;

            }


            v.push_back(nums[i]);

            dfs(cnt + 1);

            v.pop_back();


            for(int j =0;j<edges[nums[i]].size();j++){

                degree[edges[nums[i]][j]]++;

            }


            vis[nums[i]] = false;

        }


    }


}

int main(){    


    while(gets(str) != NULL){


        Init();


        int cnt = 0;

        for(int i =0;i<strlen(str);i++){


            if(str[i] <= 'z' && str[i] >= 'a'){


                nums[cnt++] = str[i] - 'a' +1;

            }

        }

        len = cnt;

        gets(str2);

        cnt = 0;

        int pre =0;

        for(int i =0;i<strlen(str2);i++){


            if(str2[i] <= 'z' && str2[i] >= 'a'){


                int now = str2[i] - 'a' +1;


                //录入边关系 加度

                if(cnt == 1) {

                    edges[pre].push_back(now);

                    cnt = 0;

                    degree[now]++;

                    continue;

                }

                if(cnt == 0){

                    pre = now; //前一点下标

                    cnt++;

                }


            }

        }

        dfs(0);

    }


    return 0;

}

3、hdu 3342 Legal or Not(简单 判断有向图 有无环路)

代码:

#include <cstdio>

#include <queue>

#include <vector>

#include <cstring>

#include <iostream>

#include <algorithm>

#define MAXN 550

using namespace std;

/*

3 2

0 1

1 2

2 2

0 1

1 0

0 0

*/

int degree[MAXN];

vector<int > edges[MAXN];

inline int read(){

    int x=0,f=1;

    char ch=getchar();

    while(ch<'0'||ch>'9'){

        if(ch=='-')

            f=-1;

        ch=getchar();

    }

    while(ch>='0'&&ch<='9'){

        x=(x<<1)+(x<<3)+(ch^48);

        ch=getchar();

    }

    return x*f;

}

void Init(int n){

    memset(edges,0,sizeof(edges));

    memset(degree,0,sizeof(degree));

}

int main(){    

    int n,m;


    while(1){


        n = read();

        m = read();


        if(n == 0 && m == 0) break;


        Init(n);


        for(int i =1;i<=m;i++){


            int a,b;


            a = read();

            b = read();


            //避免 重复边

            if(find(edges[a].begin(),edges[a].end(),b) == edges[a].end()){


                edges[a].push_back(b);  //输入边关系

                degree[b]++;  //入度加一

            }


        }


        queue<int> q;


        for(int i = 0;i<n;i++){

            if(degree[i] == 0) q.push(i);

        }


        int cnt = 0;

        while(!q.empty()){


            int u = q.front();

            q.pop();

            cnt++;

            for(int i = 0;i<edges[u].size();i++){


                int v = edges[u][i];

                if(--degree[v] == 0) q.push(v);

            }


        }


        if(cnt == n) cout <<"YES"<<endl;

        else cout << "NO" << endl;

    }


    return 0;

}

4、hdu2647 Reward (带权值得 反向建图)

代码:

#include <cstdio>

#include <queue>

#include <vector>

#include <cstring>

#include <iostream>

#include <algorithm>

#define MAXN 10005

using namespace std;

/*

3 2

0 1

1 2

2 2

0 1

1 0

0 0

*/

int w[MAXN];

int degree[MAXN];

vector<int > edges[MAXN];

inline int read(){

    int x=0,f=1;

    char ch=getchar();

    while(ch<'0'||ch>'9'){

        if(ch=='-')

            f=-1;

        ch=getchar();

    }

    while(ch>='0'&&ch<='9'){

        x=(x<<1)+(x<<3)+(ch^48);

        ch=getchar();

    }

    return x*f;

}

void Init(int n){


    memset(w,0,sizeof(w));

    memset(edges,0,sizeof(edges));

    memset(degree,0,sizeof(degree));

}

int main(){    

    int n,m;


    while(scanf("%d %d",&n,&m) != EOF){


        Init(n);


        for(int i =1;i<=m;i++){


            int a,b;


            //反向建图 便于 等下 从最底层 开始 bfs

            b = read();

            a = read();


            //避免 重复边

            if(find(edges[a].begin(),edges[a].end(),b) == edges[a].end()){


                edges[a].push_back(b);  //输入边关系

                degree[b]++;  //入度加一

            }


        }


        queue<int> q;


        for(int i = 1;i<=n;i++){

            if(degree[i] == 0) q.push(i);

        }


        int cnt = 0;

        while(!q.empty()){


            int u = q.front();

            q.pop();

            cnt++;

            for(int i = 0;i<edges[u].size();i++){


                int v = edges[u][i];

                //画图推导这里 向上赋值

                if(--degree[v] == 0) q.push(v),w[v] = w[u]+1;

            }


        }


        long long sum =0;

        if(cnt == n){

            for(int i = 1;i<=n;i++) {


                sum += w[i];

            }

            sum += 888*n;

            cout << sum<< endl;

        }

        else cout << -1 << endl;

    }


    return 0;

}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 今天学习了字符串,有字符串开头要加#include ,还有字符串的输入gets,输出puts。 以及strcpy(...
    眸若含秋水丶阅读 126评论 0 0
  • 学习了字符串数组, 1. #include #include int main(){ int i; char a[...
    于渤文阅读 56评论 0 0
  • //将原文中的'I'替换成'U' #include #include int main() { char a[20...
    Saltedfish_efd5阅读 104评论 0 0
  • 1.字符串 的简单使用 strcpy strcmp mencpy mencmp //习题 #include #in...
    王子言_853c阅读 238评论 0 0
  • 伊美喜爱的陈皮美食 新会陈皮是广东省江门市新会区的汉族传统名产。当地所产的大红柑的干果皮(也即俗称的陈皮)具有很高...
    e8d3681fa57e阅读 326评论 2 0