【算法】【图论】【C】】

4 阅读1分钟

元素-集合二分图

元素 - 集合二分图 + BFS

atcoder.jp/contests/ab…

#include <bits/stdc++.h>  
using namespace std;  
using ll=long long;  
void so(){  
      
}int main(){  
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);  
    int n,m;cin>>n>>m;  
     vector<vector<int>>g(n+m);  
    for(int i=0;i<n;i++){  
        int a;cin>>a;  
        for(int j=0;j<a;j++){  
            int s;cin>>s;--s;  
            //集合i-元素s(偏移n)  
            g[i].push_back(s+n);  
            g[s+n].push_back(i);  
        }  
    }int s=n,t=m-1+n;  
    queue<int>que;  
    vector<int>dist(n+m,-1);  
    que.push(s);  
    dist[s]=0;  
    while(!que.empty()){  
        int v=que.front();  
        que.pop();  
        for(auto v2:g[v]){  
            if(dist[v2]==-1){que.push(v2);dist[v2]=dist[v]+1;}  
        }  
    }// 答案计算(最重要!)  
    // dist[t] : 元素1 → 元素M 的最短路径长度  
    // 路径格式:元素1 → 集合 → 元素 → 集合 → ... → 元素M  
    // 每 2 步 = 使用 1 个集合  
    // 集合数 = dist[t] / 2  
    // 操作数 = 集合数 - 1  
    // --------------------  
    cout<<dist[t]/2-1;  
}

强连通分量

atcoder.jp/contests/ty…

#include <bits/stdc++.h>  
using namespace std;  
using ll=long long;  
const int N=1<<18;  
int n,m;int a[N],b[N];  
bool us[N];  
vector<int>g[N];  
vector<int>h[N];  
vector<int>I;  
ll cnts;  
//记录后序遍历序列  
void dfs(int pos){  
    us[pos]=true;  
    for(int i:g[pos]){  
        if(!us[i])dfs(i);  
    }I.push_back(pos);  
}  
void dfs2(int pos){//反图  
    us[pos]=true;  
    cnts++;  
    for(int i:h[pos]){if(!us[i])dfs2(i);}  
}  
int main(){  
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);  
    cin>>n>>m;  
    for(int i=1;i<=m;i++){  
        cin>>a[i]>>b[i];  
        g[a[i]].push_back(b[i]);  
        h[b[i]].push_back(a[i]);  
    }for(int i=1;i<=n;i++){  
        if(!us[i])dfs(i);  
    }ll ans=0;  
    reverse(I.begin(),I.end());  
    fill(us,us+n+1,false);  
    for(int i:I){  
        if(us[i])continue;  
        cnts=0;  
        dfs2(i);  
        ans+=cnts*(cnts-1ll)/2ll;  
    }  
    cout<<ans;  
}

思路

原图 DFS: 能到达别人的点会后结束 反图 DFS: 从后结束的点开始搜 只能搜到互相可达的点 刚好就是一个强连通分量!