码迷,mamicode.com
首页 > 编程语言 > 详细

拓扑排序找最大环最小环

时间:2019-10-08 12:18:58      阅读:114      评论:0      收藏:0      [点我收藏+]

标签:sort   c++   排序   ems   pre   getc   namespace   mes   lock   

找最大环 P5145 漂浮的鸭子

题意很明确:求图中的最大环

今天新学到的一种方法——拓扑排序求环

由于拓扑排序每次都是从入度为0的点开始,而环上的点的入度都不会为0,所以环上的点就不会参加排序,也就是说,经过拓扑排序后剩下的边和点构成的都是环。

这样我们就可以直接把每个环扫一遍记录最大环就结束了。


//2019/09/27 
#include<bits/stdc++.h>
using namespace std;
template <typename T>inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;}
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(int i=(a);i>=(b);--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define ee(i,u) for(int i=head[u];i;i=e[i].next)

const int N=1e5+10;
struct edge{
    int v,next,w;
}e[N];

int head[N],edge_num;
inline void add(int u,int v,int w){e[++edge_num].v=v;e[edge_num].w=w;e[edge_num].next=head[u];head[u]=edge_num;}

int n,ans;
int deg[N];

queue<int>q;
inline void topo_sort(){
    while(!q.empty()){
        int u=q.front();q.pop();
        ee(i,u){
            int v=e[i].v;
            if(--deg[v]==0)
                q.push(v);
        }
    }
}

inline void get_ring(){
    int res=0;
    while(!q.empty()){
        int u=q.front();q.pop();
        ee(i,u){
            int v=e[i].v,w=e[i].w;
            if(!deg[v])continue;
            res+=w;
            deg[v]--;
            q.push(v);
        }
    }
    ans=max(ans,res);
}

int main(){
    #ifdef WIN32
    freopen("","r",stdin);
    #endif
    rd(n);
    rep(i,1,n){
        int v,w;rd(v),rd(w);
        deg[v]++;
        add(i,v,w);
    }
    rep(i,1,n)
        if(!deg[i])
            q.push(i);
    topo_sort();
    rep(i,1,n)
        if(deg[i]){
            q.push(i);
            get_ring();
        }
    printf("%d",ans);
    return 0;
}

找最小环 noip2015 信息传递

由于环上的点的数量==边的数量,所以建图的时候给每条边连上权值为1的边权即可找到最小环。


//2019/09/27 
#include<bits/stdc++.h>
using namespace std;
template <typename T>inline void rd(T &x){x=0;char c=getchar();int f=0;while(!isdigit(c)){f|=c=='-';c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}x=f?-x:x;}
#define rep(i,a,b) for(int i=(a);i<=(b);++i)
#define dwn(i,a,b) for(int i=(a);i>=(b);--i)
#define mem(a,b) memset(a,b,sizeof(a))
#define ee(i,u) for(int i=head[u];i;i=e[i].next)

const int N=2e5+10;
struct edge{
    int v,next,w;
}e[N];

int head[N],edge_num;
inline void add(int u,int v,int w){e[++edge_num].v=v;e[edge_num].w=w;e[edge_num].next=head[u];head[u]=edge_num;}

int n,ans=INT_MAX;
int deg[N];

queue<int>q;
inline void topo_sort(){
    while(!q.empty()){
        int u=q.front();q.pop();
        ee(i,u){
            int v=e[i].v;
            if(--deg[v]==0)
                q.push(v);
        }
    }
}

inline void get_ring(){
    int res=0;
    while(!q.empty()){
        int u=q.front();q.pop();
        ee(i,u){
            int v=e[i].v,w=e[i].w;
            if(!deg[v])continue;
            res+=w;
            deg[v]--;
            q.push(v);
        }
    }
    ans=min(ans,res);
}

int main(){
    #ifdef WIN32
    freopen("","r",stdin);
    #endif
    rd(n);
    rep(i,1,n){
        int v;rd(v);
        deg[v]++;
        add(i,v,1);
    }
    rep(i,1,n)
        if(!deg[i])
            q.push(i);
    topo_sort();
    rep(i,1,n)
        if(deg[i]){
            q.push(i);
            get_ring();
        }
    printf("%d",ans);
    return 0;
}

拓扑排序找最大环最小环

标签:sort   c++   排序   ems   pre   getc   namespace   mes   lock   

原文地址:https://www.cnblogs.com/sjsjsj-minus-Si/p/11634669.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!