边连通分量/缩点-POJ3177-Redundant Paths
来源:互联网 发布:excel一行数据分成多行 编辑:程序博客网 时间:2024/06/05 10:46
用tarjan 的强连通分量增加了两句话得到的求边连通分量的方法
也就是因为无向图加了两条边之后有连回去的边,所以要判断下一个子节点是不是父亲节点,其余的和有向图的强连通分量没差。
这个算法就是记录两个时间戳,一个是index,一个是low。不断dfs。然后通过子节点更新low 这样把子节点更新完之后,属于同一个边连通分量(可以两条路径经过同一个点,但是不能经过通一条边的叫做边连通分量)的点都入栈了。然后当前时间戳即为最小时间戳,此时退栈并记录节点。
<pre name="code" class="cpp">stack<int>sta;void init2(){ e = 0; memset(head,-1,sizeof(head));}struct p1{ int index,low;}nar[SIZE_D];int Dindex,scc;int used[SIZE_D],insta[SIZE_D],belong[SIZE_D],num[SIZE_D],par[SIZE_D];void inittarjan(){ Dindex = 0; memset(insta,0,sizeof(insta)); scc = 0; memset(num,0,sizeof(num));}void tarjan(int ver){ used[ver] = 1; nar[ver].index = Dindex;//记录当前的时间戳 nar[ver].low = Dindex;//记录最早的时间戳 Dindex++;//时间戳++; sta.push(ver);//当前节点入栈 insta[ver] = 1; for (int i = head[ver]; i != -1; i = pra[i].next){ int u = pra[i].to; if (used[u] == -1){//遍历子节点。如果子节点没有被访问过,则dfspar[u] = ver; tarjan(u); nar[ver].low = min(nar[ver].low, nar[u].low);//最早的时间戳更新 }else{ if (insta[u] == 1)//如果已经在栈内。更新当前的最早时间戳if (u != par[ver]) nar[ver].low = min(nar[ver].low, nar[u].low); } } if (nar[ver].low == nar[ver].index){//dfs结束后回到了最早的时间戳的那个顶点 scc++; int w; do{ w = sta.top();//出栈 sta.pop(); insta[w] = 0; belong[w] = scc;//记录这个节点属于哪个连通分量 num[scc]++;//这个连通分量里面的节点个数加一 }while (w != ver);//直到取到当前节点为止。 }}
题意:让你最少加多少条边可以没有桥(就是去掉这条边,就不连通了。这条边就是桥),可能会有重边
题解:缩点——用tarjan 的边连通分量可以缩点。
然后结果就是(出度为1的点的个数+1)/ 2
判断每个节点是否和子节点属于同一个连通分量,如果不属于。那么这两个连通分量自加1,注意是强连通分量+1不是顶点+1
因为是无向图 所以出度为2就是有向图里的出度为1
这个重边好坑啊!
思考重边会不会对结果造成影响,然后读入的时候要判断一下有没有重边。引申,读入还要判断一下有没有自环!!!(自己连到自己的节点上)
思考重边会不会对结果造成影响,然后读入的时候要判断一下有没有重边。引申,读入还要判断一下有没有自环!!!
思考重边会不会对结果造成影响,然后读入的时候要判断一下有没有重边。引申,读入还要判断一下有没有自环!!!
思考重边会不会对结果造成影响,然后读入的时候要判断一下有没有重边。引申,读入还要判断一下有没有自环!!!
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<stack>#define SIZE_D 5005#define SIZE_B 50005using namespace std;int e,head[SIZE_D];struct pp{ int to,next;}pra[SIZE_B];void addedge(int x,int y){ pra[e].to = y; pra[e].next = head[x]; head[x] = e++; pra[e].to = x; pra[e].next = head[y]; head[y] = e++;}int repeat(int x, int y){ for (int i = head[x]; i != -1; i = pra[i].next){ if (pra[i].to == y) return 0; } return 1;}int out[SIZE_D];int D,B;stack<int>sta;void init2(){ e = 0; memset(head,-1,sizeof(head));}struct p1{ int index,low;}nar[SIZE_D];int Dindex,scc;int used[SIZE_D],insta[SIZE_D],belong[SIZE_D],num[SIZE_D],par[SIZE_D];void inittarjan(){ Dindex = 0; memset(insta,0,sizeof(insta)); scc = 0; memset(num,0,sizeof(num));}void tarjan(int ver){ used[ver] = 1; nar[ver].index = Dindex;//记录当前的时间戳 nar[ver].low = Dindex;//记录最早的时间戳 Dindex++;//时间戳++; sta.push(ver);//当前节点入栈 insta[ver] = 1; for (int i = head[ver]; i != -1; i = pra[i].next){ int u = pra[i].to; if (used[u] == -1){//遍历子节点。如果子节点没有被访问过,则dfspar[u] = ver; tarjan(u); nar[ver].low = min(nar[ver].low, nar[u].low);//最早的时间戳更新 }else{ if (insta[u] == 1)//如果已经在栈内。更新当前的最早时间戳if (u != par[ver]) nar[ver].low = min(nar[ver].low, nar[u].low); } } if (nar[ver].low == nar[ver].index){//dfs结束后回到了最早的时间戳的那个顶点 scc++; int w; do{ w = sta.top();//出栈 sta.pop(); insta[w] = 0; belong[w] = scc;//记录这个节点属于哪个连通分量 num[scc]++;//这个连通分量里面的节点个数加一 }while (w != ver);//直到取到当前节点为止。 }}int main(){ //freopen("input.txt","r",stdin); while (~scanf("%d %d",&D,&B)){ inittarjan(); init2(); for (int i = 1; i <= B; i++){ int tempx,tempy; scanf("%d %d",&tempx,&tempy); if (repeat(tempx,tempy)) addedge(tempx,tempy); } memset(used,-1,sizeof(used)); for (int i = 1; i <= D; i++) if (used[i] == -1){ par[i] = -1; tarjan(i); } //tarjan(); int res = 0; memset(out,0,sizeof(out)); for (int i = 1; i <= D; i++){//在别的题目里面有可能不是1到D为序号!! for (int j = head[i]; j != -1;j = pra[j].next){ int u = pra[j].to; if (belong[pra[j].to] != belong[i]){//判断每个节点是否和子节点属于同一个连通分量,如果不属于。那么这两个连通分量自加1,注意是强连通分量+1不是顶点+1 out[belong[pra[j].to]]++; out[belong[i]]++; } //printf("delong[%d] = %d belong[%d] = %d\n",i,belong[i],u,belong[u]); } } //printf("%d\n",scc); for (int i =1; i <= scc; i++) if (out[i] == 2){//注意,因为是无向图 所以出度为2就是有向图里的出度为1 //printf("i=%d\n",i); res++; } printf("%d\n",(res+1)/2); } return 0;}
0 0
- 边连通分量/缩点-POJ3177-Redundant Paths
- poj3177—Redundant Paths(缩点+边双联通分量)
- POJ3177 Redundant Paths —— 边双联通分量 + 缩点
- poj3177 Redundant Paths(边双连通分量+缩点)
- 【POJ3177】Redundant Paths-边双连通分量+缩点
- POJ3177 Redundant Paths (双联通缩点)
- POJ3177 Redundant Paths【边双联通分量】【Tarjan】
- poj 3177 Redundant Paths (边双联通分量+缩点)
- POJ 3177 Redundant Paths 边双联通分量 缩点
- POJ 3177 Redundant Paths(边连通分量)
- poj3177 Redundant Paths 边双连通分量
- poj3177 Redundant Paths(边双联通)
- poj3177 - Redundant Paths
- POJ3177--Redundant Paths
- 【POJ3177】Redundant Paths
- poj3177 Redundant Paths
- poj3177 Redundant Paths
- POJ3177 Redundant Paths
- 文件的读取和输出
- itoa函数的实现
- Python--sorted
- 项目5-数组做数据成员
- Android ocr识别文字介绍
- 边连通分量/缩点-POJ3177-Redundant Paths
- 第三周【项目5-数组做数据成员】
- 第三周 项目二 三角形类2
- 2--三角形
- 第3周项目2——三角形类2
- 第三周项目2三角形类2
- 第三周 项目二 三角形类2
- 解决Oracle数据库中汉字长度的问题
- 第三周项目:三角形类2