ACM图论常用模板(自用)

一直想找个时间整理一下自己常用的模板,方便自己查找。
图论还有很多算法,后期待完善。

最小生成树

kruskal

  • hdu1233
    也可以用贪心的方法,先定义一个数组,排序后并查集。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 20005;
struct Node
{
    int x,y,val;
    Node(){}
    Node(int a,int b,int c):x(a),y(b),val(c){}
    bool operator<(const Node& a)const 
    {
        return val > a.val;
    }
};
int B[maxn];
int Find(int n)
{
    return n == B[n] ? n:B[n]=Find(B[n]);
}
int main()
{
    // ios::sync_with_stdio(false);
    // cin.tie(0);
    int N = 0;
    while(scanf("%d",&N)&&N){
        priority_queue<Node> Q;
        int a,b,c;
        int T = N*(N-1)/2;
        for(int i=1;i<=T;i++){
            B[i] = i;
        }
        for(int i=1;i<=T;i++){
            scanf("%d%d%d",&a,&b,&c);
            Q.push(Node(a,b,c));
        }
        int cnt = 0;
        int ans = 0;
        while(!Q.empty()&&cnt<N-1){
            Node t = Q.top();Q.pop();
            int t1 = Find(t.x);
            int t2 = Find(t.y);
            if(t1!=t2){
                B[t2] = t1;
                ans += t.val;
                cnt++;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

生成树计数

SPOJ-HIGH

#include<bits/stdc++.h>
typedef long long LL;
typedef unsigned long long ULL;
typedef long double LD;
using namespace std;

#define MaxN 15
#define MaxM MaxN*MaxN

struct Matrix  
{  
    LL a[MaxN][MaxN];   
    LL* operator[](int x)  
    {  
        return a[x];  
    }  
    LL det(int n)  
    {    
        LL ret = 1;  
        for(int i = 1; i < n; i++)  
        {  
            for(int j = i + 1; j < n; j++)  
                while(a[j][i])  
                {  
                    LL tmp = a[i][i] / a[j][i];  
                    for(int k = i; k < n; k++) a[i][k] = (a[i][k] - a[j][k]*tmp) ;  
                    for(int k = i; k < n; k++) swap(a[i][k], a[j][k]);  
                    ret = -ret;  
                }  
            if(a[i][i] == 0) return 0;  
            ret = ret*a[i][i] ;  
        }  
        return ret;  
    }  
}; 

int n,m;
int main()
{
    int T;
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &n, &m);
        Matrix G,ans;
        memset(ans.a,0,sizeof(ans.a));
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
                G.a[i][j] = (i==j);
        int u,v;
        while(m--) 
        {
            scanf("%d%d", &u, &v);
            u--,v--;
            G.a[u][v] = G.a[v][u] = 1;
        }
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                if(i!=j && G.a[i][j])
                {
                    ans.a[i][i]++;
                    ans.a[i][j] = -1;
                }
            }
        printf("%lld\n", abs(ans.det(n)) );
    }
}

prim算法

大体上和Dijksra算法相似

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
const int maxn = 105;
typedef pair<int,int> pii;
int G[maxn][maxn];
int dis[maxn];
int N = 0;
bool vis[maxn];

int prim()
{
    int ans = 0;
    memset(dis,0x7f,sizeof(dis));
    memset(vis,0,sizeof(vis));
    priority_queue<pii,vector<pii>,greater<pii> > Q;
    Q.push(pii(0,0));
    dis[0] = 0;
    while(!Q.empty()){
        pii t = Q.top();
        Q.pop();
        int u = t.first;
        int v = t.second;
        if(vis[v]) continue;
        vis[v] = 1;
        ans += u;
        for(int i=0;i<N;i++){
            if(i!=v){
                int d = G[v][i];
                if(dis[i] > d&&!vis[i]){ //唯一和dijkstra算法不一样的地方
                    dis[i] = d;          // 
                    Q.push(pii(dis[i],i));
                }
            }
        }
    }
    return ans;
}

int main(int argc, char const *argv[])
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    while(cin >> N){
        for (int i = 0; i < N; i++)
        {
            for (int j = 0; j < N; j++)
            {
                cin >> G[i][j];
            }
        }
        cout << prim() << endl;
    }
    return 0;
}

最短路

dijkstra算法

  • poj2387
    用vecotr邻接表来表示图,适用于稀疏图
    优先队列版本的dijkstra算法。
#include<iostream>
#include<queue>
#include<cstring>
#include<vector>
using namespace std;
const int maxn = 10005;
int T,N;
vector<int> G[maxn];
vector<int> D[maxn];
int dis[maxn];
const int inf = 1<<31;
typedef pair<int,int> pii;

int dijkstra()
{
    memset(dis,10,sizeof(dis));
    bool vis[maxn];
    memset(vis,0,sizeof(vis));
    priority_queue<pii,vector<pii>,greater<pii> > Q;
    Q.push(pii(0,1));
    while(!Q.empty()){
        pii t = Q.top();
        Q.pop();
        int d = t.first;
        int a = t.second;
        if(vis[a])continue;
        vis[a] = 1;
        for(int i=0;i<G[a].size();i++){
            int j = G[a][i];
            int di = D[a][i];
            if(dis[j] > di + d){
                dis[j] = di + d;
                Q.push(pii(dis[j],j));
            }
        }
    }
    return dis[N];
}

int main()
{
    cin >> T >> N;
    int a,b,c;
    for(int i=0;i<T;i++){
        cin >> a >> b >> c;
        G[a].push_back(b);
        G[b].push_back(a);
        D[a].push_back(c);
        D[b].push_back(c);
    }
    cout << dijkstra() << endl;

    return 0;
}

bellman_ford算法

  • poj3259
    前M条边是双向边,后W条边是单向边,然后直接用bellman_ford算法判负环(自己用spfa判负环 结果WA了,不知道是测试数据卡spfa还是我spfa写错了)。
#include<iostream>
#include<algorithm>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
const int maxn = 1005;
typedef pair<int,int> pii;
int dis[maxn];
int N,M,W;
int k=0;

struct Edge 
{
    int to,from,cost;
};
Edge E[5000];

bool bellman_Ford()
{
    memset(dis,0,sizeof(dis));
    for(int i=1;i<=N;i++){
        for(int j=0;j<k;j++){
            Edge e = E[j];
            if(dis[e.to] > dis[e.from] + e.cost){
                dis[e.to] = dis[e.from] + e.cost;
                if(i==N) return false;
            }
        }
    }
    return true;
}

int main(int argc, char const *argv[])
{
    int T = 0;
    cin >> T;
    while(T--){
        cin >> N >> M >> W;
        k = 0;
        int a,b,c;
        for(int i=0;i<M;i++){
            cin >> E[k].from >> E[k].to >> E[k].cost;
            E[k+1].from = E[k].to;
            E[k+1].to = E[k].from;
            E[k+1].cost =  E[k].cost;
            k += 2;
        }
        for(int i=0;i<W;i++){
            cin >> E[k].from >> E[k].to >> E[k].cost;
            E[k].cost = -E[k].cost;
            k++;
        }
        bool ok = bellman_Ford();
        if(ok){
            cout << "NO" <<  endl;
        }else{
            cout << "YES" << endl;
        }
    }
    return 0;
}

SPFA算法

poj2240

#include<vector>
#include<algorithm>
#include<cstdio>
#include<iostream>
#include<set>
#include<cstring>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<int,pii> PII;
const int maxn = 105;
const int maxm = 1e6+5;
const int inf = 1<<30;
struct Edge 
{
    int from,to;
    double cost;
    Edge(){}
    Edge(int a,int b,double c):from(a),to(b),cost(c){}
};
Edge E[maxm];
int N,M;
vector<int> G[maxn];
map<string,int> money;
double dis[maxn];
int vis[maxn],p[maxn],cnt[maxn];

bool spfa()
{
    queue<int> Q;
    memset(vis,0,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    vis[0] = 1;
    for(int i=0;i<N;i++){
        dis[i] = 0;
        Q.push(i);
    }
    dis[0] = 1;
    while(!Q.empty()){
        int u = Q.front();
        Q.pop();
        vis[u] = 0;
        for(int i=0;i<G[u].size();i++){
            Edge e = E[G[u][i]];
            double t = dis[e.from] * e.cost;
            if(dis[e.to] < t){
                dis[e.to] = t;
                p[e.to] = G[u][i];
                if(!vis[e.to]){
                    Q.push(e.to);
                    vis[e.to] = 1;
                    if(++cnt[e.to]> N)return false;
                }
            }
        }
    }
    return true;
}

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int Case = 1;
    while(cin >> N,N){
        money.clear();
        string s;
        for(int i=0;i<N;i++){
            cin >> s;
            money[s] = i;
            G[i].clear();
        }
        cin >> M;
        double t;
        string s2;
        for(int i=0;i<M;i++){
            cin >> s >> t >> s2;
            int f = money[s],to = money[s2];
            E[i] = Edge(f,to,t);
            G[f].push_back(i);
        }
        bool ok = spfa();
        cout << "Case "<< Case++ << ": ";
        if(!ok){
            cout << "Yes" << endl;
        }else{
            cout << "No" << endl;
        }
    }
    
    return 0;
}

Flody算法

for (int i = 0; i < n; i++) {   //  初始化为0  
    for (int j = 0; j < n; j++)  
        scanf("%lf", &dis[i][j]);  
}  
for (int k = 0; k < n; k++) {  
    for (int i = 0; i < n; i++) {  
        for (int j = 0; j < n; j++) {  
            dis[i][j] = min(dis[i][j], dis[i][k] + dis[k][j]);  
        }  
    }
}

网络流

增广路算法

  • 计蒜课排涝
    模板题
    EdmondsKarp也可用于二分图的最大基数匹配,在二分图的左边后右边都添加一个结点,然后分别和二分图两边的结点相连即可。
#include <bits/stdc++.h>

using namespace std;
const int maxn = 205;
const int INF = 1<<30;
struct Edge
{
    int from,to,cap,flow;
    Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};

struct Dinic        //更快
{
    int n,m,s,t;
    vector<Edge> edges;
    vector<int> G[maxn];
    bool vis[maxn];
    int d[maxn];
    int cur[maxn];

    void init(int n){
        for(int i=0;i<n;i++) G[i].clear();
        edges.clear();
    }

    void AddEdge(int from,int to,int cap){
        edges.push_back(Edge(from,to,cap,0));
        edges.push_back(Edge(to,from,0,0));
        m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }

    bool BFS()
    {
        memset(vis,0,sizeof(vis));
        queue<int> Q;
        Q.push(s);
        d[s] = 0;
        vis[s] = 1;
        while(!Q.empty()){
            int x = Q.front();
            Q.pop();
            for(int i=0;i<G[x].size();i++){
                Edge& e = edges[G[x][i]];
                if(!vis[e.to]&&e.cap > e.flow){
                    vis[e.to] = 1;
                    d[e.to] = d[x]+1;
                    Q.push(e.to);
                }
            }
        }
        return vis[t];
    }

    int DFS(int x,int a){
        if(x==t || a==0)return a;
        int flow = 0,f;
        for(int &i=cur[x];i<G[x].size();i++){
            Edge& e = edges[G[x][i]];
            if(d[x]+1==d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0){
                e.flow += f;
                edges[G[x][i]^1].flow -= f;
                flow += f;
                a -= f;
                if(a==0)break;
            }
        }
        return flow;
    }

    int Maxflow(int s,int t){
        this->s = s,this->t = t;
        int flow = 0;
        while(BFS()){
            memset(cur,0,sizeof(cur));
            flow += DFS(s,INF);
        }
        return flow;
    }
    
};

struct EdmondsKarp
{
    int n,m;
    vector<Edge> edges;
    vector<int> G[maxn];
    int a[maxn];
    int p[maxn];

    void init(int n){
        for(int i=0;i<n;i++) G[i].clear();
        edges.clear();
    }

    void AddEdge(int from,int to,int cap){
        edges.push_back(Edge(from,to,cap,0));
        edges.push_back(Edge(to,from,0,0));
        m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }

    int Maxflow(int s,int t){
        int flow = 0;
        while(1){
            memset(a,0,sizeof(a));
            queue<int> Q;
            Q.push(s);
            a[s] = INF;
            while(!Q.empty()){
                int x = Q.front();Q.pop();
                for(int i=0;i<G[x].size();i++){
                    Edge& e = edges[G[x][i]];
                    if(!a[e.to]&&e.cap>e.flow){
                        p[e.to] = G[x][i];
                        a[e.to] = min(a[x],e.cap-e.flow);
                        Q.push(e.to);
                    }
                }
                
                if(a[t]) break;
            }
            if(!a[t])break;
            for(int u=t;u!=s;u=edges[p[u]].from){
                edges[p[u]].flow += a[t];
                edges[p[u]^1].flow -= a[t];
            }
            flow += a[t];
        }
        return flow;
    }
};

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n,m;
    cin >> n >> m;
    EdmondsKarp s;
    int a,b,c;
    for(int i=0;i<n;i++){
        cin >> a >> b >>c;
        s.AddEdge(a,b,c);
    }
    cout << s.Maxflow(1,m) <<endl;
}

最小费用最大流

给定流量,求最小费用
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<int,pii> PII;
const int INF = 0x3f3f3f3f;

const int maxn = 1005;
struct Edge{
    int to,cap,cost,rev;
};

int V;
vector<Edge> G[maxn];
int dis[maxn];
int prevv[maxn],preve[maxn];

void add_edge(int from,int to,int cap,int cost)
{
    G[from].push_back((Edge){to,cap,cost,(int)G[to].size()});
    G[to].push_back((Edge){from,0,-cost,(int)G[from].size()-1});
}

int min_cost_flow(int s,int t,int f)
{
    int res = 0;
    while(f>0){
        memset(dis,0x3f,sizeof(dis));
        dis[s] = 0;
        bool update = true;
        while(update){
            update = false;
            for(int v = 0;v < V;v++){
                if(dis[v]==INF)continue;
                for(int i=0;i<G[v].size();i++){
                    Edge &e = G[v][i];
                    if(e.cap > 0&& dis[e.to] > dis[v] + e.cost){
                        dis[e.to] = dis[v] + e.cost;
                        prevv[e.to] = v;
                        preve[e.to] = i;
                        update = true;
                    }
                }
            }
        }
        if(dis[t]==INF){
            return -1;
        }
        int d = f;
        for(int v = t;v!=s;v=prevv[v]){
            d = min(d,G[prevv[v]][preve[v]].cap);
        }
        f -= d;
        res += d*dis[t];
        for(int v=t;v!=s;v=prevv[v]){
            Edge& e = G[prevv[v]][preve[v]];
            e.cap -= d;
            G[v][e.rev].cap += d;
        }
    }
    return res;
}


int main(int argc, char const *argv[])
{
    int N,M;
    int a,b,c;
    scanf("%d %d",&N,&M);
    V = N;
    for(int i=0;i<M;i++){
        scanf("%d%d%d",&a,&b,&c);
        add_edge(a,b,1,c);
        add_edge(b,a,1,c);
    }
    cout << min_cost_flow(1,N,2) << endl;
    
    return 0;
}
流量输出最大流时,求最小的费用
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int INF = 1<<30;

const int maxn = 10005;
struct Edge{
    int from ,to,cap,flow,cost;
    Edge(int u,int v,int c,int f,int w):from(u),to(v),cap(c),flow(f),cost(w){}
};

struct MCMF{
    int n,m;
    vector<Edge> edges;
    vector<int> G[maxn];
    int inq[maxn];  //是否在队列中
    int d[maxn];    //Bellman-Ford
    int p[maxn];    //上一条弧
    int a[maxn];    //可改进量

    void init(int n)
    {
        this-> n = n;
        for(int i=0;i<n;i++){
            G[i].clear();
        }
        edges.clear();
    }

    void AddEdge(int from,int to,int cap,int cost)
    {
        edges.push_back(Edge(from,to,cap,0,cost));
        edges.push_back(Edge(to,from,0,0,-cost));
        m = edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }
    
    bool BellmanFord(int s,int t,int& flow,ll& cost)
    {
        for(int i=0;i<n;i++) d[i] = INF;
        memset(inq,0,sizeof(inq));
        d[s] = 0;inq[s]  = 1;p[s] = 0;a[s] = INF;

        queue<int> Q;
        Q.push(s);
        while(!Q.empty()){
            int u = Q.front();Q.pop();
            inq[u] = 0;
            for(int i=0;i<G[u].size();i++){
                Edge& e = edges[G[u][i]];
                if(e.cap > e.flow && d[e.to] > d[u] + e.cost){
                    d[e.to] = d[u] + e.cost;
                    p[e.to] = G[u][i];
                    a[e.to] = min(a[u],e.cap - e.flow);
                    if(!inq[e.to]){
                        Q.push(e.to);
                        inq[e.to] = 1;
                    }
                }
            }
        }
        if (d[t] == INF)
            return false;
        flow += a[t];
        cost += (ll)(d[t] * a[t]);
        int u = t;
        while (u != t){
            edges[p[u]].flow += a[t];
            edges[p[u] ^ 1].flow -= a[t];
            u = edges[p[u]].from;
        }

        return true;
    }

    int MincostMaxflow(int s,int t,ll& cost){
        int flow = 0;cost = 0;
        while(BellmanFord(s,t,flow,cost));
        return flow;
    }
};

二分图

二分图判断(交叉染色)

static int speed_up = []() {
     ios::sync_with_stdio(false);
     cin.tie(nullptr);
     return 0;
 }();
const int MAX_N = 2005;
int V;
vector<int> G[MAX_N];

int color[MAX_N];
 
bool dfs(int v, int c)
{
    color[v] = c; 
    for(int i = 0; i < G[v].size(); i++)
    {
        int j = G[v][i];
        if(color[j] == c)
            return false;
        if(color[j] == 0 && !dfs(j, -c))
            return false;
    }
    return true;
}
 
bool solve()
{
    for(int i = 1; i <= V; i++)
    {
        if(color[i] == 0)
        {
            if(!dfs(i,1))
            {
                
                return false;
            }
        }
    }
    return true;
}


class Solution {
public:
    bool possibleBipartition(int N, vector<vector<int>>& dislikes) {
        V = N;
        for(int i=0;i<=N;i++){
            G[i].clear();
        }
       memset(color,0,sizeof(color));
        for(int i=0;i<dislikes.size();i++){
            int u = dislikes[i][0];
            int v = dislikes[i][1];
            
            G[u].push_back(v);
            G[v].push_back(u);
        }
        return solve();
    }
};

最大匹配

poj3941

#include<vector>
#include<algorithm>
#include<cstdio>
#include<iostream>
#include<set>
#include<cstring>
#include<functional>
#include<map>
#include<cmath>
#include<string>
#include<stack>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<int,pii> PII;
const int maxn = 1005;
vector<int> G[maxn];
int match[maxn];
int used[maxn];
int V;

void add_edge(int u,int v)
{
    G[u].push_back(v);
    G[v].push_back(u);
}

bool dfs(int v)
{
    used[v] = true;
    for(int i=0;i<G[v].size();i++){
        int u = G[v][i],w = match[u];
        if(w <0 || (!used[w]&&dfs(w))){
            match[u] = v;
            match[v] = u;
            return true;
        }
    }
    return false;
}

int bitpartite_match()
{
    int ans = 0;
    memset(match,-1,sizeof(match));
    for(int i=1;i<=V;i++){
        if(match[i] < 0){
            memset(used,0,sizeof(used));
            if(dfs(i)){
                ans++;
            }
        }
    }
    return ans;
}

int main(int argc, char const *argv[])
{
    int N,K;
    cin >> N >> K;
    int a,b;
    V = 2*N;
    for(int i=0;i<K;i++){
        cin >> a >> b;
        add_edge(a,b+N);
    }

    cout << bitpartite_match() << endl;
    
    return 0;
}

无向图割边割点和双连通分量

#include <bits/stdc++.h>
using namespace std;
#define mclear(x) memset((x), 0, sizeof((x)))
typedef pair<int, int> pii;
const int MAX = 5100;
int n, m, deep;
vector<int> path[MAX];
int vis[MAX], low[MAX];
vector<int> cutpoint; //割点
vector<pii> bridge;   //割边,桥
int nbcc;             //双连通分量数
stack<pii> order;
vector<int> bcc[MAX]; //双连通分量

void dfs(int pos, int father)
{
    int i, j, total = 0;
    bool cut = false;
    int reback = 0; //处理平行边
    vis[pos] = low[pos] = deep++;
    int ls = path[pos].size();
    for (j = 0; j < ls; j++)
    {
        i = path[pos][j];
        if (i == father)
            reback++;
        if (vis[i] == 0)
        {
            pii e(pos, i);
            order.push(e);
            dfs(i, pos);
            if (low[i] >= vis[pos])
            {
                nbcc++;
                bcc[nbcc].clear();
                pii r;
                do
                {
                    r = order.top();
                    order.pop();
                    bcc[nbcc].push_back(r.second);
                } while (e != r);
                bcc[nbcc].push_back(r.first);
            }
            total++;
            low[pos] = min(low[i], low[pos]);
            if ((vis[pos] == 1 && total > 1) ||
                (vis[pos] != 1 && low[i] >= vis[pos]))
                cut = true;
            if (low[i] > vis[pos])
                bridge.push_back(e);
        }
        else if (i != father)
        {
            low[pos] = min(vis[i], low[pos]);
        }
    }
    if (reback > 1)
        low[pos] = min(low[pos], vis[father]);
    if (cut)
        cutpoint.push_back(pos);
}
void find_cut()
{
    int i;
    mclear(vis);
    mclear(low);
    cutpoint.clear();
    bridge.clear();
    nbcc = 0;
    while (!order.empty())
        order.pop();
    for (i = 1; i <= n; i++)
    {
        if (vis[i] == 0)
        {
            deep = 1;
            dfs(i, -1);
        }
    }
}

int main()
{
    while (~scanf("%d", &n) && n)
    {
        int a = 0;
        char c;
        vector<int> vet;
        for (int i = 0; i <= n; i++)
        {
            path[i].clear();
        }
        int u = 0;
        while (scanf("%d", &u) && u)
        {
            while (scanf("%c", &c)&&c==' ')
            {
                scanf("%d",&a);
                path[u].push_back(a);
                path[a].push_back(u);
            }
        }
        find_cut();
        cout << cutpoint.size() << endl;
    }

    return 0;
}

强连通分量

SCC的Tarjan算法

#include<iostream>
#include<cstring>
#include<queue>
#include<cstdio>
#include<stack>
#include<algorithm>
#include<vector>

using namespace std;
const int maxn = 105;
vector<int> G[maxn];
bool M[maxn][maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
int out[maxn],in[maxn];
stack<int> S;

int dfs(int u)
{
    pre[u] = lowlink[u] = ++dfs_clock;
    S.push(u);
    for(int i=0;i<G[u].size();i++){
        int v = G[u][i];
        if(!pre[v]){
            dfs(v);
            lowlink[u] = min(lowlink[u],lowlink[v]);
        }else if(!sccno[v]){
            lowlink[u] = min(lowlink[u],pre[v]);
        }
    }
    if(lowlink[u] == pre[u]){
        scc_cnt++;
        while(1){
            int x = S.top();S.pop();
            sccno[x] = scc_cnt;
            if(x==u)break;
        }
    }
}

void find_scc(int n)
{
    dfs_clock = scc_cnt = 0;
    memset(sccno,0,sizeof(sccno));
    memset(pre,0,sizeof(pre));
    memset(out,0,sizeof(out));
    memset(in,0,sizeof(in));
    for(int i=1;i<=n;i++){
        if(!pre[i])dfs(i);
    }
    if(scc_cnt==1){
        cout << "1\n0\n";
        return;
    }
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(M[i][j]&&sccno[i]!=sccno[j]){
                out[sccno[i]]++;
                in[sccno[j]]++;
            }
        }
    }
    int ans1 = 0,ans2 = 0;
    for(int i=1;i<=scc_cnt;i++){
        if(in[i]==0)ans1++;
        if(out[i]==0)ans2++;
    }
    cout << ans1 << endl << max(ans1,ans2) << endl;
}


int main()
{
    int N  = 0;
    cin >> N;
    int a = 0;
    for(int i=1;i<=N;i++){
        while(cin >> a&&a){
            G[i].push_back(a);
            M[i][a] = 1;
        }
    }
    
    find_scc(N);

    return 0;
}

转载于:https://www.cnblogs.com/django-lf/p/9717223.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值