LOJ #2877. 「JOISC 2014 Day2」交朋友 并查集+BFS

这种图论问题都挺考验小思维的.   

首先,我们把从 $x$ 连出去两条边的都合并了.  

然后再去合并从 $x$ 连出去一条原有边与一条新边的情况.  

第一种情况直接枚举就行,第二种情况来一个多源 bfs 即可. 

code:

#include <cstdio> 
#include <string>
#include <vector>
#include <queue>      
#include <algorithm>
#define N 100006    
#define ll long long 
using namespace std; 
namespace IO 
{   
    inline void setIO(string s) 
    {
        string in=s+".in"; 
        string out=s+".out"; 
        freopen(in.c_str(),"r",stdin);  
        // freopen(out.c_str(),"w",stdout);  
    }
};              
int edges;     
queue<int>q;    
vector<int>G[N];    
int size[N],p[N],out[N],vis[N];          
inline void add(int u,int v) { G[u].push_back(v); }   
inline int find(int x)   { return p[x]==x?x:p[x]=find(p[x]); }   
inline void initialize() { for(int i=0;i<N;++i) size[i]=1,p[i]=i; }
int main() 
{
    // IO::setIO("input");  
    int i,j,n,m;      
    initialize();  
    scanf("%d%d",&n,&m);                        
    for(i=1;i<=m;++i) 
    {
        int x,y;  
        scanf("%d%d",&x,&y),++out[x],add(x,y);  
    }   
    for(i=1;i<=n;++i) 
    {   
        for(j=1;j<G[i].size();++j) 
        {
            int pr=G[i][j-1],cur=G[i][j];     
            if(find(pr)!=find(cur)) 
            {
                pr=find(pr),cur=find(cur);   
                p[pr]=cur,size[cur]+=size[pr];   
            }
        }
    }                                  
    for(i=1;i<=n;++i) 
    {
        int x=find(i);   
        if(size[x]>1) q.push(i),vis[i]=1;      
    }
    while(!q.empty()) 
    {
        int u=q.front(); q.pop();          
        for(i=0;i<G[u].size();++i) 
        {
            int v=G[u][i];    
            if(find(v)!=find(u)) 
            {
                int a=find(u),b=find(v);     
                p[a]=b,size[b]+=size[a];           
            }
            if(!vis[v]) q.push(v),vis[v]=1;   
        }    
    }   
    ll ans=0;  
    for(i=1;i<=n;++i) 
    { 
        if(p[i]==i) 
            ans+=(size[i]>1?(ll)(size[i]-1)*size[i]:out[i]);     
    }
    printf("%lld
",ans);    
    return 0;  
}

  

原文地址:https://www.cnblogs.com/guangheli/p/12378108.html