无向图的联通分量

无向图的联通分量环啊,桥啊,生成树的边啊,联通分量啊,就是一个东西

Unique Path https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4055

这个题是把环去掉,其他的树上有n个点,就有n*(n-1)/2 对。

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #include<vector>
  5 #include<queue>
  6 #include<stack>
  7 #define mt(a,b) memset(a,b,sizeof(a))
  8 using namespace std;
  9 typedef long long LL;
 10 class Tarjan_U { ///无向图连通分量缩点o(MV+ME)
 11     typedef int typec;///边权的类型
 12     static const int ME=200010;///边的个数
 13     static const int MV=10010;///点的个数
 14     struct Q{
 15         int u,v;
 16         typec w;
 17     }now;
 18     vector<Q> qiao;
 19     int Bcnt,Index,num[MV],dfn[MV],low[MV],belong[MV];
 20     stack<int> s;
 21     void addqiao(int u,int v,typec w){
 22         now.u=u;
 23         now.v=v;
 24         now.w=w;
 25         qiao.push_back(now);
 26     }
 27     void tarjan(int u) {
 28         s.push(u);
 29         dfn[u]=low[u]=++Index;
 30         int v;
 31         for (int i=g.head[u]; ~i; i=g.e[i].next) {
 32             if(g.e[i].vis)continue;
 33             g.e[i].vis=g.e[i^1].vis=true;
 34             v=g.e[i].v;
 35             if (!dfn[v]) {
 36                 tarjan(v);
 37                 low[u]=min(low[u],low[v]);
 38                 if(dfn[u]<low[v])
 39                     addqiao(u,v,g.e[i].w);
 40             } else low[u]=min(low[u],dfn[v]);
 41         }
 42         if(dfn[u]==low[u]) {
 43             Bcnt++;
 44             do {
 45                 v=s.top();
 46                 s.pop();
 47                 belong[v]=Bcnt;
 48                 num[Bcnt]++;
 49             } while(v!=u);
 50         }
 51     }
 52 public:
 53     struct G {
 54         struct E {
 55             int v,next;
 56             bool vis;
 57             typec w;
 58         } e[ME];
 59         int le,head[MV];
 60         void init() {
 61             le=0;
 62             mt(head,-1);
 63         }
 64         void add(int u,int v,typec w) {
 65             e[le].vis=false;
 66             e[le].v=v;
 67             e[le].w=w;
 68             e[le].next=head[u];
 69             head[u]=le++;
 70         }
 71     } g;
 72     void init() {
 73         g.init();
 74         Index=Bcnt=0;
 75         mt(num,0);
 76         mt(dfn,0);
 77         mt(low,0);
 78         qiao.clear();
 79         while(!s.empty()) s.pop();
 80     }
 81     void add(int u,int v,typec w) {///双向边
 82         g.add(u,v,w);
 83         g.add(v,u,w);
 84     }
 85     void solve(int n) {///传入点数,点下标1开始
 86         for(int i=1; i<=n; i++) {
 87             if(!dfn[i]) {
 88                 tarjan(i);
 89             }
 90         }
 91     }
 92     int getbcnt() {///强连通分量的个数
 93         return Bcnt;
 94     }
 95     int getbelong(int id) {///属于哪个分量,分量下标1开始
 96         return belong[id];
 97     }
 98     int getnum(int id) {///某个分量的点的个数
 99         return num[id];
100     }
101 } T;
102 const int M=1e5+10;
103 bool vis[M],need[M];
104 queue<int> q;
105 int bfs(int s) {
106     vis[s]=true;
107     while(!q.empty()) q.pop();
108     q.push(s);
109     int res=0;
110     while(!q.empty()) {
111         int u=q.front();
112         q.pop();
113         res++;
114         for(int i=T.g.head[u]; ~i; i=T.g.e[i].next) {
115             int v=T.g.e[i].v;
116             if(!vis[v]) {
117                 vis[v]=true;
118                 q.push(v);
119             }
120         }
121     }
122     return res;
123 }
124 int main() {
125     int t,n,m;
126     while(~scanf("%d",&t)) {
127         int cas=1;
128         while(t--) {
129             scanf("%d%d",&n,&m);
130             T.init();
131             while(m--) {
132                 int u,v;
133                 scanf("%d%d",&u,&v);
134                 T.add(u,v,1);
135             }
136             T.solve(n);
137             mt(need,0);
138             for(int i=1; i<=T.getbcnt(); i++) {
139                 if(T.getnum(i)>1) need[i]=true;
140             }
141             mt(vis,0);
142             for(int i=1; i<=n; i++) {
143                 if(need[T.getbelong(i)]) {
144                     vis[i]=true;
145                 }
146             }
147             LL ans=0;
148             for(int i=1; i<=n; i++) {
149                 if(!vis[i]) {
150                     LL dian=bfs(i);
151                     ans+=dian*(dian-1)/2;
152                 }
153             }
154             printf("Case #%d: %lld\n",cas++,ans);
155         }
156     }
157     return 0;
158 }
159 /**
160 4
161 7 6
162 1 2
163 1 3
164 2 4
165 3 4
166 4 5
167 5 6
168
169
170 5 4
171 1 2
172 2 3
173 2 4
174 4 5
175
176
177 4 4
178 1 2
179 2 3
180 3 4
181 4 1
182
183
184 8 8
185 1 2
186 2 3
187 2 4
188 2 5
189 3 4
190 5 6
191 6 7
192 6 8
193
194
195 Case #1: 1
196 Case #2: 10
197 Case #3: 0
198 Case #4: 6
199
200 */

时间: 2024-07-29 04:21:18

无向图的联通分量的相关文章

51nod 1076 2条不相交的路径 无向图强联通分量 trajan算法

1076 2条不相交的路径 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 给出一个无向图G的顶点V和边E.进行Q次查询,查询从G的某个顶点V[s]到另一个顶点V[t],是否存在2条不相交的路径.(两条路径不经过相同的边) (注,无向图中不存在重边,也就是说确定起点和终点,他们之间最多只有1条路) Input 第1行:2个数M N,中间用空格分开,M是顶点的数量,N是边的数量.(2 <= M <= 25000, 1 <= N <=

无向图的双联通分量

点双和边双的区别我在上一篇文章中已经讨论过了,这篇文章讲边双的求法. 由于是边双,就决定了边双中一定不含有桥,但是可以含有割顶. 所以我们对边双唯一的限制条件就是不经过桥. 如此一来,我们可以分成两次dfs,第一次求出所有的桥,第二次dfs时遍历整张图,只要保证不经过桥就可以了. #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <s

图论——LCA、强联通分量、桥、割顶、二分图最大匹配、网络流

A: 交通运输线 时间限制: 5 Sec  内存限制: 128 MB 题目描述 战后有很多城市被严重破坏,我们需要重建城市.然而,有些建设材料只能在某些地方产生.因此,我们必须通过城市交通,来运送这些材料的城市.由于大部分道路已经在战争期间完全遭到破坏,可能有两个城市之间没有道路.当然在运输线中,更不可能存在圈. 现在,你的任务来了.给你战后的道路情况,我们想知道,两个城市之间是否存在道路,如果存在,输出这两个城市之间的最短路径长度. 输入 第一行一个整数Case(Case<=10)表示测试数据

hihocoder #1190 : 连通性&#183;四 点双联通分量

http://hihocoder.com/problemset/problem/1190?sid=1051696 先抄袭一下 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho从约翰家回到学校时,网络所的老师又找到了小Hi和小Ho. 老师告诉小Hi和小Ho:之前的分组出了点问题,当服务器(上次是连接)发生宕机的时候,在同一组的服务器有可能连接不上,所以他们希望重新进行一次分组.这一次老师希望对连接进行分组,并把一个组内的所有连接关联的服务器也视为这个组内

[HDOJ4738]Caocao&#39;s Bridges(双联通分量,割边,tarjan)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4738 给一张无向图,每一条边都有权值.找一条割边,使得删掉这条边双连通分量数量增加,求权值最小那条. 注意有重边,ACEveryDay里群巨给的意见是tarjan的时候记录当前点是从哪条边来的. 注意假如桥的权值是0的时候也得有一个人去炸…… 1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7

UVA - 10765 Doves and bombs (双联通分量)

链接 :  http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=34798 给N个点的无向图并且联通,问删除每次一个点之后还剩多少联通分量. 找割顶 如果删除的是割顶 联通分量就会增加,否则还是1(因为原图是联通图),删除割顶之后 联通块的数目 就要看该割顶在几个双联通分量里出现过. #pragma comment(linker, "/STACK:10240000,10240000") #include <a

【POJ1236】Network of Schools 强联通分量缩点(本文kosaraju)

/*不要说这题多水之类的--我只是想记一下kosaraju这种屌炸天的dfs序延伸算法(说不定能加到我的ygylca里面)*/ 题意神马的都不说了,好吧,就是给你个图,n个点,然后n行每行都描述该点的出边,图建完了,然后缩点,然后问多少个点没有入度,再问需要加几条边可以让图变强联通图. 强联通图:图中任意两点之间都能互相到达(前提得是有向图你懂的,无向图就有点乱了,根本不要算法了,暴搜就好了) 强联通分量:同强联通图,不过是图中一部分. 缩点,把一个分量视为一个点,缩起来(一般不缩,都是记录每个

HDU5409---CRB and Graph 2015多校 双联通分量缩点

题意:一个联通的无向图, 对于每一条边, 若删除该边后存在两点不可达,则输出这两个点, 如果存在多个则输出第一个点尽可能大,第二个点尽可能小的. 不存在输出0 0 首先 若删除某一条边后存在多个联通分量则该边一定是桥, 那么我们可以先处理出所有的桥,然后把所有双联通分量缩点,缩点之后就变成了一棵树. 而树上的每一条边都是一个桥, 考虑每条边的输出,删除某一边后肯定会出现两个联通分量, 需要记录两个联通分量中最大的点max1 max2, 如果max1!=n 则答案就是max1 max1+1否则ma

Tarjan的强联通分量

求强联通分量有很多种. <C++信息学奥赛一本通>  中讲过一个dfs求强联通分量的算法Kosdaraju,为了骗字数我就待会简单的说说.然而我们这篇文章的主体是Tarjan,所以我肯定说完之后再赞扬一下Tarjan大法好是不是 首先我们讲一下强联通分量 强联通分量指的是图的一个子图.在这个子图中,任意两个节点都可以互相到达.从定义上我们就可以看出是一个有向图来,因为任意一个无向图都符合该定义. 而它的标准定义是:有向图中任意两点都联通的最大子图. 咳咳,首先庆祝一下哈--本人博客的第一张图.