HDOJ 4612 - Warm up tarjan求无向图双联通分量+树形DP+stack申请更多空间
2013-08-06 09:16
337 查看
题意:
给一个连通无向图..两点间可能有多条边...问加一条边后..桥最少能有多少个...
题解:
之前没写过tarjan求双联通分量的...练习赛的时候思路有点乱.再加上不断的爆栈..就搞不定了..
首先求双联通分量并缩点..如果题目能保证没有重边..做了无向图tarjan后每个点的low值就代表在哪个双连通分量里....但题目就是要绕一下..那么就先求出哪些边是桥..然后dfs染色..碰到桥不过去..就行..再将颜色相同的点缩成一个..做边....这时这个图就成了一颗树..题目是说加一条边后..要让桥最少..显然是要连接某两个度为1的点( 叶子节点或者说只有一个孩子的根节点)...链接这两点后..又出来一个双联通块..双联通块中的桥全部变成非桥..题目再次转化..求用双联通缩点后的树中的最长链..很典型的树形DP....
题目恶心的是会爆栈...真心不想手动写栈做dfs了...提供一种方法..再程序上方加入#pragma comment(linker,"/STACK:102400000,102400000") 用C++提交就行
Program:
给一个连通无向图..两点间可能有多条边...问加一条边后..桥最少能有多少个...
题解:
之前没写过tarjan求双联通分量的...练习赛的时候思路有点乱.再加上不断的爆栈..就搞不定了..
首先求双联通分量并缩点..如果题目能保证没有重边..做了无向图tarjan后每个点的low值就代表在哪个双连通分量里....但题目就是要绕一下..那么就先求出哪些边是桥..然后dfs染色..碰到桥不过去..就行..再将颜色相同的点缩成一个..做边....这时这个图就成了一颗树..题目是说加一条边后..要让桥最少..显然是要连接某两个度为1的点( 叶子节点或者说只有一个孩子的根节点)...链接这两点后..又出来一个双联通块..双联通块中的桥全部变成非桥..题目再次转化..求用双联通缩点后的树中的最长链..很典型的树形DP....
题目恶心的是会爆栈...真心不想手动写栈做dfs了...提供一种方法..再程序上方加入#pragma comment(linker,"/STACK:102400000,102400000") 用C++提交就行
Program:
#pragma comment(linker,"/STACK:102400000,102400000") //申请栈空间..用C++提交 #include<iostream> #include<stdio.h> #include<string.h> #include<cmath> #include<queue> #include<stack> #include<set> #include<map> #include<algorithm> #define ll long long #define eps 1e-5 #define oo 1000000007 #define pi acos(-1.0) #define MAXN 200005 #define MAXM 2000005 using namespace std; struct node { int x,y,id,next; }line[MAXM]; int Lnum,_next[MAXN],dfn[MAXN],low[MAXN],DfsIndex,dp[MAXN],tp[MAXN],tpnum,MM; bool used[MAXN],brige[MAXM]; void addline(int x,int y,int id) { line[++Lnum].next=_next[x],_next[x]=Lnum; line[Lnum].x=x,line[Lnum].y=y; line[Lnum].id=id; } void tarjan(int x,int id) { int y,k; dfn[x]=low[x]=++DfsIndex; for (k=_next[x];k;k=line[k].next) { if (line[k].id==id) continue; y=line[k].y; if (!dfn[y]) { tarjan(y,line[k].id); low[x]=min(low[x],low[y]); if (dfn[x]<low[y]) brige[k]=true; }else low[x]=min(low[x],dfn[y]); } return; } void dfs0(int x) { int k; tp[x]=tpnum; for (k=_next[x];k;k=line[k].next) if (!tp[line[k].y] && !brige[k]) dfs0(line[k].y); } void dfs(int x) { int y,k; dp[x]=0; used[x]=true; for (k=_next[x];k;k=line[k].next) { y=line[k].y; if (used[y]) continue; dfs(y); MM=max(MM,dp[x]+dp[y]+1); dp[x]=max(dp[x],dp[y]+1); } return; } int main() { int N,M,i; freopen("input.txt","r",stdin); freopen("output.txt","w",stdout); while (~scanf("%d%d",&N,&M) && ( N || M) ) { Lnum=0; memset(_next,0,sizeof(_next)); while (M--) { int x,y; scanf("%d%d",&x,&y); addline(x,y,M),addline(y,x,M); } memset(dfn,0,sizeof(dfn)); memset(brige,false,sizeof(brige)); DfsIndex=0; tarjan(1,-1); tpnum=0; memset(tp,0,sizeof(tp)); for (i=1;i<=N;i++) if (!tp[i]) { tpnum++; dfs0(i); } memset(_next,0,sizeof(_next)); int x,y,temp=Lnum; Lnum=0; for (i=1;i<=temp;i++) { x=tp[line[i].x],y=tp[line[i].y]; if (x==y) continue; addline(x,y,0); } memset(used,false,sizeof(used)); MM=0; dfs(1); printf("%d\n",tpnum-1-MM); } return 0; }
相关文章推荐
- hdoj 2242 考研路茫茫——空调教室 【无向图求边双联通 缩点 + 树形dp】
- hdu 4612 (双联通+树形DP)
- hdu 4612 (双联通+树形DP)
- hdu 4612 Warm up 双连通+树形dp思想
- HDOJ 3861 - The King’s Problem tarjan求强联通分量&缩点&有向图最小路径覆盖(匈牙利)
- Tarjan(无向图双联通分量)——hihoCoder 1184
- hdu 2242双联通分量+树形dp
- hdu 4612 Warm up 双连通+树形dp思想
- hdu 2242双联通分量+树形dp
- [HDOJ4738]Caocao's Bridges(双联通分量,割边,tarjan)
- HDU 4612 Warm up 边双联通分量,树宽
- UVALive5135 [Mining Your Own Business] tarjan求无向图双联通分量
- HDU 4612 and 4607 (tarjan求桥+树形dp求树的直径)
- 4612 warm up tarjan+bfs求树的直径(重边的强连通通分量)忘了写了,今天总结想起来了。
- HDOJ 1827 - Summer Holiday 简单的tarjan求强联通分量+缩点
- UVALive3523 [Knights of the Round Table] tarjan求无向图双联通分量
- [笔记]tarjan-无向图(桥、割点、双联通分量)
- HDU 4612 Warm up 树的最长路径DP + 无向图带重边
- HDOJ 4280 - Island Transport 裸最大流(Dinic) ..申请更多栈空间...
- BZOJ2140: 稳定婚姻 Tarjan求无向图强联通分量