zoukankan      html  css  js  c++  java
  • 图论2——拓扑排序

    拓扑排序:*保证无环 

    1:模板(若要字典序则采用优先队列)

    #include<iostream>
    #include<cstring>
    #include<queue> 
    int s[100010],f[100010];
    int vis[100010];
    using namespace std;
    int main()
    {
    int n,m,i,temp,flag,u,v;
    queue<int> q;
    //priority_queue<int, vector<int>, greater<int> > q;
    memset(s,0,sizeof(s));
    memset(f,0,sizeof(f));
    cin>>n>>m;
    for (i=1;i<=m;i++)
    {
    cin>>u>>v;
    s[v]++;
    f[u]=f[u]+v;
    f[v]=f[v]+u;
    }
    for (i=1;i<=n;i++)
    {
    if (s[i]==0) 
    {
    q.push(i);
    vis[i]=1;
    }
    }
    flag=0;
    while (!q.empty())
    {
    temp=q.front();
    q.pop();
    f[f[temp]]-=temp;
    s[f[temp]]--;
    //temp=q.top();
    if (flag) 
    {
    cout<<" ";
    flag=1;
    }
    cout<<temp;
    if (s[f[temp]]==0&&!vis[f[temp]]) 
    {
    q.push(f[temp]);
    vis[f[temp]]=1;
    }
    }
    cout<<endl;
    return 0;
    }
    2:建立超级汇点

    即,存在多个连通块,进行字典序拓扑。先用并查集分块。exm:ZOJ - 4109

    AC代码:

    #include<queue>
    #include<cstring>
    #include<stdio.h>
    #include<iostream>
    #include<vector>
    using namespace std; 
    int edge[2000010],next[2000010],end[1000010];
    bool vis[1000010];
    int ans[1000010];
    int f[1000010];
    int find(int m)
    {
    if (m==f[m]) return m;
    else return find(f[m]);
    }
    void merge(int i,int t)
    {
    int t1=find(i);
    int t2=find(t);
    if (t1==t2) return;
    if (t1>t2) f[t1]=t2;
    else f[t2]=t1;
    }
    int main()
    {
    long long t,n,m,minj,num,sum,jj,k,j,i,u,v,p;
    priority_queue<int, vector<int>, greater<int> > q;
    scanf("%lld",&t);
    for (k=1;k<=t;k++)
    {
    scanf("%lld%lld",&n,&m);
    for (i=0;i<=n;i++)
    {
    f[i]=i;
    vis[i]=0;
    end[i]=0;
    }
    for (i=1;i<=m;i++)
    {
    scanf("%lld%lld",&u,&v);
    merge(u,v);
    if (end[u]==0)
    {
    end[u]=i*2-1;
    edge[i*2-1]=v;
    next[i*2-1]=0;
    }
    else
    {
    next[i*2-1]=end[u];
    edge[i*2-1]=v;
    end[u]=i*2-1;
    }
    if (end[v]==0)
    {
    end[v]=i*2;
    edge[i*2]=u;
    next[i*2]=0;
    }
    else
    {
    next[i*2]=end[v];
    edge[i*2]=u;
    end[v]=i*2;
    }
    }
    sum=0;
    for (i=1;i<=n;i++)
    {
    if (i==f[i]) 
    {
    sum++;
    ans[sum]=i;
    }
    }
    cout<<sum<<endl;
    for (i=1;i<=sum;i++)
    {
    vis[ans[i]]=1;
    q.push(ans[i]);
    }
    while (!q.empty())
    {
    if (q.top()!=1) cout<<" ";
    cout<<q.top();
    p=end[q.top()];
    q.pop();
    while (p!=0)
    {
    if (!vis[edge[p]]) 
    {
    q.push(edge[p]); 
    vis[edge[p]]=1;
    }
    p=next[p]; 
    }
    }
    cout<<endl;
    }
    return 0;
    }

     

  • 相关阅读:
    es5预览本地文件、es6练习代码演示案例
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 838 推多米诺(暴力模拟)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 837 新21点(DP)
    Java实现 LeetCode 836 矩形重叠(暴力)
    Subversion under Linux [Reprint]
    Subversion how[Reprint]
  • 原文地址:https://www.cnblogs.com/idyllic/p/10827501.html
Copyright © 2011-2022 走看看