Codeforce 505D - Mr. Kitayuta's Technology 弱联通分量+拓扑排序

对于有向图M,若将其所有的边转化为无向边,则得到其基图M‘,若M’是联通的,则称有向图M是弱联通。

对于有向图M,若图中任意两点u,v(u != v)均满足u到v可达,v到u可达,则称此图为强联通。

根据以上定义显然可知,强联通图一定也满足弱联通。

此题首先我们需要找到其所有的弱联通分量。

对于每一个弱联通分量,设此弱联通分量内点的个数为ans,如果此联通分量无环,则需要的边数为ans-1,若有环则为ans。

太挫了,这种题都不会了,怎么变黄!!!

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <stack>
#include <map>

#pragma comment(linker, "/STACK:1024000000")
#define EPS (1e-8)
#define LL long long
#define ULL unsigned long long
#define _LL __int64
#define INF 0x3f3f3f3f
#define Mod 6000007

//** I/O Accelerator Interface .. **/
#define g (c=getchar())
#define d isdigit(g)
#define p x=x*10+c-'0'
#define n x=x*10+'0'-c
#define pp l/=10,p
#define nn l/=10,n
template<class T> inline T& RD(T &x)
{
    char c;
    while(!d);
    x=c-'0';
    while(d)p;
    return x;
}
template<class T> inline T& RDD(T &x)
{
    char c;
    while(g,c!='-'&&!isdigit(c));
    if (c=='-')
    {
        x='0'-g;
        while(d)n;
    }
    else
    {
        x=c-'0';
        while(d)p;
    }
    return x;
}
inline double& RF(double &x)      //scanf("%lf", &x);
{
    char c;
    while(g,c!='-'&&c!='.'&&!isdigit(c));
    if(c=='-')if(g=='.')
        {
            x=0;
            double l=1;
            while(d)nn;
            x*=l;
        }
        else
        {
            x='0'-c;
            while(d)n;
            if(c=='.')
            {
                double l=1;
                while(d)nn;
                x*=l;
            }
        }
    else if(c=='.')
    {
        x=0;
        double l=1;
        while(d)pp;
        x*=l;
    }
    else
    {
        x=c-'0';
        while(d)p;
        if(c=='.')
        {
            double l=1;
            while(d)pp;
            x*=l;
        }
    }
    return x;
}
#undef nn
#undef pp
#undef n
#undef p
#undef d
#undef g

using namespace std;

vector<int>  vec[100010];
vector<int> wvec[100010];
int deg[100010];
bool mark[100010];
bool cir;
int ans;

struct Q
{
    int v,d;
    bool operator < (const Q &a)const{
        return a.d < d;
    }
};

priority_queue<Q> q;

void FindCir()
{
    Q f;
    int i;

    while(q.empty() == false)
    {
        f = q.top();
        q.pop();

        if(deg[f.v] < f.d)
            continue;

        if(f.d)
        {
            cir = true;
            return ;
        }

        for(i = wvec[f.v].size()-1;i >= 0; --i)
        {
            --deg[wvec[f.v][i]];
            q.push((Q){wvec[f.v][i],deg[wvec[f.v][i]]});
        }
    }
}

void FindAns(int site,int pre = -1)
{
    if(mark[site])
        return ;

    mark[site] = true;

    ans++;

    q.push((Q){site,deg[site]});

    for(int i = vec[site].size()-1;i >= 0; --i)
    {
        if(vec[site][i] != pre)
            FindAns(vec[site][i],site);
    }
}

int main()
{
    int u,v,i,n,m,sum;

    scanf("%d %d",&n,&m);
    memset(deg,0,sizeof(deg));
    for(i = 1;i <= m; ++i)
    {
        scanf("%d %d",&u,&v);

        wvec[u].push_back(v);
        deg[v]++;

        vec[u].push_back(v);
        vec[v].push_back(u);
    }

    memset(mark,false,sizeof(mark));

    sum = 0;

    for(i = 1;i <= n; ++i)
    {
        if(mark[i] == false)
        {
            ans = 0;

            while(q.empty() == false)
                q.pop();

            FindAns(i);

            cir = false;

            FindCir();

            sum += cir ? ans : ans-1;
        }
    }

    printf("%d\n",sum);

    return 0;
}






















郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。