拓扑排序

作者: 彬雨 | 来源:发表于2020-04-07 19:58 被阅读0次

    一、拓扑排序

     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;

    }

    相关文章

      网友评论

        本文标题:拓扑排序

        本文链接:https://www.haomeiwen.com/subject/vzlophtx.html