洛谷专题-强连通分量

P2341 [USACO03NOV][HAOI2006]受欢迎的牛 G /【模板】强连通分量

思路:

题目中问的是有多少牛受到所有牛的欢迎,因为本题具有传递性,则在图中,每个强连通分量中的奶牛都是互相喜欢的。所以,只要跑一遍Tarjan,图变成DAG有向无环图。

因为每一头奶牛都需要得到其他牛的欢迎,因此在没有环的情况下,不能再喜欢除了自环中的其它牛,即出度为0的牛是明星牛。

注意:特殊情况,如果存在一个以上的出度为0的点,则这几个子图中的奶牛都无法喜欢到其他这样子图中的奶牛(不连通)。所以输出0

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<cstdio>
 using namespace std;
 const int maxn=1e5+10;
 vector<int> a[maxn];
 int tot=0,t=0,k=0,dfs[maxn],low[maxn],stack[maxn],flag[maxn],color[maxn],cnt[maxn],out[maxn];
 void tarjan(int x)
 {
     dfs[x]=low[x]=++tot;
     stack[++k]=x;
     flag[x]=1;
     for(int i=0;i<a[x].size();i++){
         if(!dfs[a[x][i]]){
             tarjan(a[x][i]);
             low[x]=min(low[x],low[a[x][i]]);
         }
        else if(flag[a[x][i]])
            low[x]=min(low[x],dfs[a[x][i]]);
     }
    if(dfs[x]==low[x]){
        t++;
        do{
            color[stack[k]]=t,cnt[t]++;
            flag[stack[k--]]=0;
        }while(x!=stack[k+1]);
    }
 }
 int main()
 {
     int n,m,u,v;
     scanf("%d%d",&n,&m);
     for(int i=1;i<=m;i++){
         scanf("%d%d",&u,&v);
         a[u].push_back(v);
     }
    for(int i=1;i<=n;i++) if(!dfs[i]) tarjan(i);
    for(int i=1;i<=n;i++){
        for(int j=0;j<a[i].size();j++){
            if(color[i]!=color[a[i][j]]) 
                out[color[i]]++;
        }
    }
    int ans=0;
    for(int i=1;i<=t;i++){
        if(out[i]==0){
            if(ans){ cout<<0<<endl;return 0;}
            else ans=cnt[i];
        }
    }
    cout<<ans<<endl;
    return 0;
 }
View Code

P3469 [POI2008]BLO-Blockade(求割点)

思路:

如果不是割点的话,答案就为2*(n-1)

是割点的话,答案就为∑sumi* (n-sum-1)+(n-sum-1)*sum+2*(n-1),sum为其dfs子树大小

#include<iostream>
#include<algorithm>
#include<vector>
#include<cstdio>
 using namespace std;
 typedef long long ll;
 const int maxn=1e5+10;
 vector<int> a[maxn];
 ll low[maxn],dfs[maxn],siz[maxn],tot;
 ll ans[maxn],n,flag[maxn];
 ll tarjan(int x,int fa)
 {
     dfs[x]=low[x]=++tot;
    int sum=0,son=0;
     for(int i=0;i<a[x].size();i++){
         int u=a[x][i];
         if(u==fa) continue;
         if(!dfs[u]){
            ll size=tarjan(u,x);
            son+=size;
             low[x]=min(low[x],low[u]);
             if(low[u]>=dfs[x]){
                 sum+=size;
                 ans[x]+=size*(n-1-size);
             }
         }
        low[x]=min(low[x],dfs[u]);
     }
    ans[x]+=(n-sum-1)*sum;
    ans[x]+=2*(n-1);
    return son+1;
 }
 int main()
 {
     int m,u,v;
     scanf("%lld%d",&n,&m);
     for(int i=1;i<=m;i++){
         scanf("%d%d",&u,&v);
         a[u].push_back(v);
         a[v].push_back(u);
     }
    tarjan(1,0);
    for(int i=1;i<=n;i++) printf("%lld\n",ans[i]);
    return 0;
  } 
View Code

 

posted @ 2020-02-27 17:36  overrate_wsj  阅读(262)  评论(0编辑  收藏  举报