深度理解拓扑排序

概念:

  一个有向无环图的拓扑序列是将图中的顶点排成一个线性序列,使得对于图中任意一对顶点u,v。若存在边<u,v>,则线性序列中u出现在v之前。

算法实现:

(1)若图中的点入度均大于0则不存在拓扑序列,否则进行第二步

(2)取一个入度为0的点u并将其放置序列末尾

(3)删除点u以及从u伸出的边,即将与u相连的点的入度减1

(4)若图中还存在顶点,再从(1)开始

最基础的模板:

#include <bits/stdc++.h>
using namespace std;
vector<int> v[1010];
queue<int> q;
int ans[1010];
int n,m;
void tuopu()
{
    int cnt = 0;
    while(!q.empty())
        q.pop();
    for(int i=1;i<=n;i++)
        if(in[i] == 0)
            q.push_back(i);
    while(!q.empty())
    {
        int k = q.front();
        ans[++cnt] = k;
        q.pop();
        for(int i=0;i<v[k].size();i++)
        {
            in[ v[k][i] ]--;
            if(in[ v[k][i] ] == 0)
                q.push_back(v[k][i]);
        }
    }
    for(int i=1;i<=cnt;i++)
    {
        cout<<ans[i]<<" ";
    }
    return ;
}
int main()
{
    while(cin>>n>>m &&n)
    {
        for(int i=1;i<=n;i++)
            v[i].clear();
        memset(in,0,sizeof(in));
        for(int i=1;i<=m;i++)
        {
            cin>>x>>y;
            v[x].push_back(y);
            in[y]++;
        }
        tuopu();
    }
   
    return 0;
}

 

定向题目:

1.有向图判环   HDU - 3342

#include <iostream>
#include <string.h>
#include <vector>
#include <queue>
using namespace std;
vector<int> v[110];
queue<int> q;
int in[110];
int n,m,x,y;
bool tuopu()
{
    int cnt = 0;
    while(!q.empty())
        q.pop();
    for(int i=0;i<n;i++)
        if(in[i] == 0){
            q.push(i);
            cnt++;
        }

    while(!q.empty())
    {
        int k = q.front();
        q.pop();
        for(int i=0;i<v[k].size();i++)
        {
            in[ v[k][i] ]--;
            if(in[ v[k][i] ] == 0){
                q.push(v[k][i]);
                cnt++;
            }

        }
    }
    if(cnt != n)
        return false;
    return true;
}
int main()
{
    while(cin>>n>>m &&n)
    {
        for(int i=0;i<n;i++)
            v[i].clear();
        memset(in,0,sizeof(in));
        for(int i=1;i<=m;i++)
        {
            cin>>x>>y;
            v[x].push_back(y);
            in[y]++;
        }
        if(tuopu()){
            cout<<"YES"<<endl;
        }else{
            cout<<"NO"<<endl;
        }
    }

    return 0;
}

 

2. 反向拓扑 深搜  HDU - 2647

#include <iostream>
#include <string.h>
#include <vector>
#include <queue>
using namespace std;
#define ll long long
ll money = 0;
vector<int> v[10010];
queue<int> q;
int in[10010];
int ans[10010];
int n,m,x,y;
void tuopu()
{
    int cnt = 0;
    while(!q.empty())
        q.pop();
    for(int i=1;i<=n;i++)
        if(in[i] == 0){
            q.push(i);
        }

    while(!q.empty())
    {
        int k = q.front();
        q.pop();
        cnt++;
        for(int i=0;i<v[k].size();i++)
        {
            in[ v[k][i] ]--;
            if(in[ v[k][i] ] == 0){
                q.push(v[k][i]);
                ans[v[k][i]] = max(ans[k]+1,ans[v[k][i]]);
            }
        }
    }
    if(cnt == n)
    {
        money = 888*n;
        for(int i=1;i<=n;i++)
        {
            money += ans[i];
        }
        cout<<money<<endl;
    }else{
        cout<<"-1"<<endl;
    }
    return ;
}
int main()
{
    while(cin>>n>>m && n)
    {
        for(int i=1;i<=n;i++)
            v[i].clear();
        memset(in,0,sizeof(in));
        memset(ans,0,sizeof(ans));
        for(int i=1;i<=m;i++)
        {
            cin>>x>>y;
            v[y].push_back(x);
            in[x]++;
        }
        tuopu();
    }

    return 0;
}

 3.正反拓扑 和 dfs ZOJ - 4124

#include <iostream>
#include <string.h>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
int n,m,k1,k2;
vector<int> v1[110];
vector<int> v2[110];
queue<int> q;
int sign[110];
int in1[110];

bool tuopu()
{
    while(!q.empty())
        q.pop();
    int cnt = 0;
    for(int i=1;i<=n;i++)
        if(in1[i] == 0)
            q.push(i);
    while(!q.empty())
    {
        int k = q.front();
        q.pop();
        cnt++;
        in1[k] = -1;
        for(int i=0;i<v1[k].size();i++)
        {
            in1[ v1[k][i] ]--;
            if(in1[ v1[k][i] ] == 0)
                q.push(v1[k][i]);
        }
    }
    if(cnt != n)
        return false;
    return true;
}

void dfs1(int x)
{
    sign[x] = 1;
    for(int i=0;i<v1[x].size();i++)
    {
        if(!sign[v1[x][i]]){
            k1++;
            dfs1(v1[x][i]);
        }
    }
    return ;
}
void dfs2(int x)
{
    sign[x] = 1;
    for(int i=0;i<v2[x].size();i++)
    {
        if(!sign[v2[x][i]]){
            k2++;
            dfs2(v2[x][i]);
        }
    }
    return ;
}
int main()
{
    int t,x,y;
    cin>>t;
    while(t--)
    {
        for(int i=1;i<=n;i++){
            v1[i].clear();
            v2[i].clear();
        }
        memset(in1,0,sizeof(in1));

        cin>>n>>m;
        for(int i=1;i<=m;i++)
        {
            cin>>x>>y;
            v1[x].push_back(y);
            v2[y].push_back(x);
            in1[y]++;
        }
        if(tuopu())
        {
            for(int i=1;i<=n;i++)
            {
                k1 = k2 = 0;
                memset(sign,0,sizeof(sign));
                dfs1(i);
                memset(sign,0,sizeof(sign));
                dfs2(i);
                if(k1 <= (n-1)/2 && k2 <= (n-1)/2)
                    cout<<"1";
                else
                    cout<<"0";
            }
            cout<<endl;
        }else{
            for(int i=1;i<=n;i++)
                cout<<"0";
            cout<<endl;
        }
    }
    return 0;
}
全部评论

相关推荐

整顿职场的柯基很威猛:这种不可怕,最可怕的是夹在一帮名校里的二本选手,人家才是最稳的。
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务