Codeforces K. Ice Skating(求强连通分量)

题目描述:

Ice Skating

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Bajtek is learning to skate on ice. He‘s a beginner, so his only mode of transportation is pushing off from a snow drift to the north, east, south or west and sliding until he lands in another snow drift. He has noticed that in this way it‘s impossible to get from some snow drifts to some other by any sequence of moves. He now wants to heap up some additional snow drifts, so that he can get from any snow drift to any other one. He asked you to find the minimal number of snow drifts that need to be created.

We assume that Bajtek can only heap up snow drifts at integer coordinates.

Input

The first line of input contains a single integer n (1?≤?n?≤?100) — the number of snow drifts. Each of the following n lines contains two integers *x**i* and *y**i* (1?≤?xi,?yi?≤?1000) — the coordinates of the i-th snow drift.

Note that the north direction coinсides with the direction of Oy axis, so the east direction coinсides with the direction of the Ox axis. All snow drift‘s locations are distinct.

Output

Output the minimal number of snow drifts that need to be created in order for Bajtek to be able to reach any snow drift from any other one.

Examples

Input

Copy

2
2 1
1 2

Output

Copy

1

Input

Copy

2
2 1
4 1

Output

Copy

0

思路:

题目是说给一些点,这些点只有在x坐标相同或者y坐标相同才能相互连接,现在为了让这些点能够全部连通问需要再加几个点。这题一开始可能会觉得有点麻烦,因为这是好多个点,我怎么知道那些点能够相互连通那些点不能,加点又要加在什么地方。但其实不用考虑加点在什么地方,我们只需要关注哪些点是连通的就行了。把这些点建成一个图,可以连通的建一条边,然后就是图上的强连通分量的数目了。一个强连通分量内点是可以相互到达的,有n个强连通分量我们就把强连通分量再连起来这些点就组成了一个强连通分量。怎么连,只要再建n-1条边就行了。这n-1条边实际上就对应的是加建的点。然而我忘了tarjan怎么写,照抄书上的另一种算法,但好像那个模板有点问题,于是看了tarjan再写就对了。

代码:

#include <iostream>
#include <stack>
#include <vector>
#define max_n 1005
using namespace std;
typedef pair<int,int> PII;
vector<PII> vec;
int head[max_n];
int cnt = 0;
struct edge
{
    int v;
    int nxt;
}e[max_n<<1];
void add(int u,int v)
{
    ++cnt;
    e[cnt].v = v;
    e[cnt].nxt = head[u];
    head[u] = cnt;
}
int n,m;
int idx = 0;
int Bcnt;
int instack[max_n];
int dfn[max_n];
int low[max_n];
int belong[max_n];
stack<int> s;
void tarjan(int u)
{
    dfn[u] = low[u] = ++idx;
    s.push(u);
    instack[u]=1;
    int v;
    for(int i = head[u];i;i=e[i].nxt)
    {
        v = e[i].v;
        if(!dfn[v])
        {
            tarjan(v);
            low[u] = min(low[u],low[v]);
        }
        else if(instack[v])
        {
            low[u] = min(low[u],dfn[v]);
        }
    }
    if(dfn[u]==low[u])
    {
        Bcnt++;
        do
        {
            v=s.top();
            s.pop();
            instack[v]=0;
            belong[v]=Bcnt;
        }while(u!=v);
    }
}
int main()
{
    cin >> n;
    for(int i = 0;i<n;i++)
    {
        int x,y;
        cin >> x >> y;
        vec.push_back(PII(x,y));
    }
    for(int i = 0;i<n;i++)
    {
        for(int j = i+1;j<n;j++)
        {
            if(vec[i].first==vec[j].first||vec[i].second==vec[j].second)
            {
                add(i,j);
                add(j,i);
            }
        }
    }
    for(int i = 0;i<n;i++)
    {
        if(!dfn[i])
        {
            tarjan(i);
        }
    }
    cout << Bcnt-1 << endl;
    return 0;
}

原文地址:https://www.cnblogs.com/zhanhonhao/p/11334819.html

时间: 2025-01-15 08:45:45

Codeforces K. Ice Skating(求强连通分量)的相关文章

UESTC 901 方老师抢银行 --Tarjan求强连通分量

思路:如果出现了一个强连通分量,那么走到这个点时一定会在强连通分量里的点全部走一遍,这样才能更大.所以我们首先用Tarjan跑一遍求出所有强连通分量,然后将强连通分量缩成点(用到栈)然后就变成了一个DAG(有向无环图),然后跑一遍DFS,不断加上遍历点的权值,如果到了网吧,则更新一遍答案,因为可以出去了. 求强连通分量时,如果low[u] == dfn[u],说明形成了一个新的强连通分量,且根为u.具体求强连通分量见:http://www.cnblogs.com/whatbeg/p/377642

CCF 高速公路 tarjan求强连通分量

问题描述 某国有n个城市,为了使得城市间的交通更便利,该国国王打算在城市之间修一些高速公路,由于经费限制,国王打算第一阶段先在部分城市之间修一些单向的高速公路. 现在,大臣们帮国王拟了一个修高速公路的计划.看了计划后,国王发现,有些城市之间可以通过高速公路直接(不经过其他城市)或间接(经过一个或多个其他城市)到达,而有的却不能.如果城市A可以通过高速公路到达城市B,而且城市B也可以通过高速公路到达城市A,则这两个城市被称为便利城市对. 国王想知道,在大臣们给他的计划中,有多少个便利城市对. 输入

poj 2186 tarjan求强连通分量

蕾姐讲过的例题..玩了两天后才想起来做 貌似省赛之后确实变得好懒了...再努力两天就可以去北京玩了! 顺便借这个题记录一下求强连通分量的算法 1 只需要一次dfs 依靠stack来实现的tarjan算法 每次走到一个点 马上把它压入栈中 每次对与这个点相连的点处理完毕 判断是否low[u]==dfn[u] 若是 开始退栈 直到栈顶元素等于u才退出(当栈顶元素等于u也需要pop) 每次一起退栈的点属于同一个强连通分量 储存图可以用链式前向星也可以用邻接矩阵更可以用vector 蕾姐说不会超时 我信

UVALive 4262——Trip Planning——————【Tarjan 求强连通分量个数】

Road Networks Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Submit Status Practice UVALive 4262 Description There is a road network comprised by M<tex2html_verbatim_mark> roads and N<tex2html_verbatim_mark> cities.

Tarjan 算法求 LCA / Tarjan 算法求强连通分量

[时光蒸汽喵带你做专题]最近公共祖先 LCA (Lowest Common Ancestors)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili tarjan LCA - YouTube Tarjan算法_LCA - A_Bo的博客 - CSDN博客 Tarjan离线算法求最近公共祖先(LCA) - 初学者 - CSDN博客 最近公共祖先(LCA) - riteme.site Fuzhou University OnlineJudge P3379 [模板]最近公共祖先(LCA) - 洛谷 |

POJ-3180 The Cow Prom(tarjan求强连通分量)

题目链接:http://poj.org/problem?id=3180 题目大意:求一个有向图的强连通分量 算法:求强连通分量首选tarjan算法 这里简单说一下tarjan的思路 时间戳是什么:在搜索时访问的最早时间 维护dfn[u]表示u的时间戳 low[u]表示u点所能回到的最早的祖先的时间戳 开一个栈,把搜索的点入栈.搜索时遇到已经搜过的点,取low[u]和dfn[v]的最小值,回溯时取low[u]和low[v]的最小值(标记上传)传到dfn[u]<=low[u]时表示已经回溯到最上面的

转 tarjan算法求强连通分量

无意中想起图的强连通分量来,之前也一直想写所以今天决定来填这个坑.PS:由于本人比较懒,之前做过一个讲解的PPT,不过那是好遥远之前,年代已久早已失传,所以本文里的图来自网络.以后周末都用来填坑也挺好. ------------------------------分割线----------------------------------------- 在有向图G中,如果两个顶点间至少存在一条路径,那么这两个顶点就是强连通(strongly connected). 如果有向图G的每两个顶点都强连通

hdu 1269 tarjan求强连通分量

tarjan求强连通分量的裸题复习,直接上代码: 1 #include <stack> 2 #include <cstdio> 3 #include <cstring> 4 using namespace std; 5 6 const int N = 10001; 7 const int M = 100000; 8 int dfn[N], low[N], head[N]; 9 bool inStack[N]; 10 int n, m, e, cnt, dfs_clock

poj1236 Network of Schools ,求强连通分量(Tarjan算法),缩点

题目链接: 点击打开链接 题意: 给定一个有向图,求: 1) 至少要选几个顶点,才能做到从这些顶点出发,可以到达全部顶点 2) 至少要加多少条边,才能使得从任何一个顶点出发,都能到达全部顶点 顶点数<= 100 求完强连通分量后,缩点,计算每个点的入度,出度. 第一问的答案就是入度为零的点的个数, 第二问就是max(n,m) // 入度为零的个数为n, 出度为零的个数为m. //kuangbin巨巨分析很棒! #include<cstdio> #include<cstring>