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;
}

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

时间: 2024-11-08 23:51:12

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

Codeforces Round #286 div.2 D 505D. Mr. Kitayuta&#39;s Technology【强连通分量,弱联通分量】

题目链接:http://codeforces.com/contest/505/problem/D 题目大意: 在一个图中,有n个顶点,给出m对数字(u,v)表示顶点u和顶点v必须直接或者间接相连,让你构造一个这样的图,输出最少需要多少条边. 分析: 毫无疑问,n个顶点的话,我们最多可以用n条边,使得n个顶点构成一个环,满足所有的情况(任意两点都是联通的),但是这并不一定是最少的边. 于是我们还需要找一个方法确定最少需要多少条边. 首先我们利用题目给出的点对建图,得到图G.对于G中的弱联通分量来说

CodeForces 506B/505D Mr. Kitayuta&#39;s Technology

Portal:http://codeforces.com/problemset/problem/506/B http://codeforces.com/problemset/problem/505/D 好题 给n个城市,m条有向边,求出最少的有向边使得其构成的图与原图等势 对于每个连通分量: 如果无环,那么只需要需要n-1条边完成联通 如果有环,则只需要n条边完成联通 所以这题只要判下连通分量,再看有几个连通分量有环即可 解法一:无向图遍历求强连通分量再把强连通分量所代表的联通分量dfs判环,如

hihoCoder #1185 : 连通性&#183;三(强联通分量+拓扑排序)

#1185 : 连通性·三 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 暑假到了!!小Hi和小Ho为了体验生活,来到了住在大草原的约翰家.今天一大早,约翰因为有事要出去,就拜托小Hi和小Ho忙帮放牧. 约翰家一共有N个草场,每个草场有容量为W[i]的牧草,N个草场之间有M条单向的路径. 小Hi和小Ho需要将牛羊群赶到草场上,当他们吃完一个草场牧草后,继续前往其他草场.当没有可以到达的草场或是能够到达的草场都已经被吃光了之后,小hi和小Ho就把牛羊群赶回家. 一开

【CF505D】Mr. Kitayuta&#39;s Technology

题目大意: 在一个有向图中,有n个顶点,给出m对数字(u,v)表示顶点u和顶点v必须直接或者间接相连,让你构造一个这样的图,输出最少需要多少条边. 挖坑待填 官方题解链接:http://codeforces.com/blog/entry/15889. 传送门:http://www.codeforces.com/problemset/problem/505/D [CF505D]Mr. Kitayuta's Technology

codeforces 505 D Mr. Kitayuta&#39;s Technology

题意:给出n个点,m条有向边,问构造一个新图,最少几条边可以让任意两点间的连通性跟原图一样. 做法:首先做出强连通分量,很显然对于有向图而言,若分图的点不唯一必定成环,当然啦,还需要做的是把这些分图再连起来变成弱连通分量,若某个弱连通分量的点数为v,若有环则贡献v条边,否则贡献v-1条边. #include<map> #include<string> #include<cstring> #include<cstdio> #include<cstdlib

POJ 2762 Going from u to v or from v to u?(强联通,拓扑排序)

http://poj.org/problem?id=2762 Going from u to v or from v to u? Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 14573   Accepted: 3849 Description In order to make their sons brave, Jiajia and Wind take them to a big cave. The cave has

POJ 2186-Popular Cows (图论-强联通分量Korasaju算法)

题目链接:http://poj.org/problem?id=2186 题目大意:有n头牛和m对关系, 每一对关系有两个数(a, b)代表a牛认为b牛是“受欢迎”的,且这种关系具有传递性, 如果a牛认为b牛“受欢迎”, b牛认为c牛“受欢迎”, 那么a牛也认为c牛“受欢迎”. 现在想知道有多少头牛受除他本身外其他所有牛的欢迎? 解题思路:如果有两头或者多头牛受除他本身外其他所有牛的欢迎, 那么在这两头或者多头牛之中, 任意一头牛也受两头或者多头牛中别的牛的欢迎, 即这两头或者多头牛同属于一个强联

poj 2762 Going from u to v or from v to u? (判断是否是弱联通图)

题意:给定一个有向图有m条单向边,判断是否任意两点都可达(a能到b或者b能到a或者互相可达),即求 弱联通分量. 算法: 先缩点求强连通分量.然后重新建图,判断新图是否是一条单链,即不能分叉,如果分叉了就会存在不可达的情况. 怎么判断是否是单链呢? 就是每次入度为0的点都只有一个,即每次队列里只有一个点. (    o(╯□╰)o.....好像已经是第二次用pair记录原图的点对,然后存pair的vector忘记清空导致wa来wa去! ) #include<cstdio> #include&l

Codeforces Round #286 div.1 D 506D D. Mr. Kitayuta&#39;s Colorful Graph【并查集】

题目链接:http://codeforces.com/problemset/problem/506/D 题目大意: 给出n个顶点,m条边,每条边上有一个数字,代表某个颜色.不同数字代表不同的颜色.有很多个询问,每个询问问有多少条纯种颜色的路径使得某两个点联通. 分析: 这个题一看就想用并查集来搞,每种颜色用一个并查集处理.对于输入的每条边,我们只需要将这两个点在这条边的颜色对应的并查集中合并就好了.查询的时候,我们只需要检测这两个点在多少个颜色对应的并查集中是在统一集合中的,那么就有多少条纯种颜