hdu--3836--tarjan+缩点
2014-08-23 21:04
281 查看
缩点 很简单的啊... 就是将原来一个连通块变成一个点..
可能你原本是这样的 A->B->C->A 缩点完成后 我们就把{A,B,C}用数字1来表示 如果还有D->E->D 那我们再讲{D,E}用2表示....
最后的sum就是代表连通块总的个数
然后 一般 缩点完成后 我们现在得到了n个连通块 我们要考虑的是 最少需要添加几条边来把它串联起来
这样考虑
假如给你2个点 A B 想要让他们联通 需要在他们之间建立两条边 分别是A->B B->A 你会发现这样 A B的入度 出度分别从0变成了1
如果是这样的情况
View Code
因为 这里的数组要开的TM的实在是太多了 所以我用了 (n)*sizeof(int)来初始化 我测了下 节约了15ms....
today:
后来我终于知道
它并不是我的花
我只是恰好途径了它的盛放
可能你原本是这样的 A->B->C->A 缩点完成后 我们就把{A,B,C}用数字1来表示 如果还有D->E->D 那我们再讲{D,E}用2表示....
最后的sum就是代表连通块总的个数
然后 一般 缩点完成后 我们现在得到了n个连通块 我们要考虑的是 最少需要添加几条边来把它串联起来
这样考虑
假如给你2个点 A B 想要让他们联通 需要在他们之间建立两条边 分别是A->B B->A 你会发现这样 A B的入度 出度分别从0变成了1
如果是这样的情况
#include <iostream> #include <cstring> #include <algorithm> #include <stack> using namespace std; int n , cnt , index , sum; const int size = 20010; struct data { int st; int end; }node[size*3]; struct graph { int to; int next; }edge[size*3]; int head[size]; int father[size]; int No[size]; int scc[size]; int in[size]; int out[size]; bool vis[size]; stack<int>s; void init( ) { memset( head , -1 , int*sizeof(n+10) ); memset( No , 0 , int*sizeof(n+10) ); memset( father , 0 , int*sizeof(n+10) ); memset( vis , false , int*sizeof(n+10) ); memset( scc , 0 , int*sizeof(n+10) ); memset( in , 0 , int*sizeof(n+10) ); memset( out , 0 , int*sizeof(n+10) ); } void add( int st , int end ) { edge[cnt].to = end; edge[cnt].next = head[st]; head[st] = cnt ++; } void tarjan( int u ) { int v , temp; No[u] = father[u] = index++; vis[u] = true; s.push(u); for( int i = head[u] ; ~i ; i = edge[i].next ) { v = edge[i].to; if( !No[v] ) { tarjan(v); father[u] = min( father[u] , father[v] ); } else if( vis[v] ) { father[u] = min( father[u] , No[v] ); } } if( father[u] == No[u] ) { sum ++; while(1) { temp = s.top(); s.pop(); vis[temp] = false; scc[temp] = sum; if( father[temp] == No[temp] ) break; } } } int main() { cin.sync_with_stdio(false); int m , st , end , inMax , outMax; while( cin >> n >> m ) { inMax = outMax = cnt = sum = 0; index = 1; init(); for( int i = 0 ; i<m ; i++ ) { cin >> st >> end; add( st , end ); node[i].st = st; node[i].end = end; } for( int i = 1 ; i<=n ; i++ ) { if( !No[i] ) tarjan(i); } for( int i = 0 ; i<m ; i++ ) { if( scc[ node[i].st ]!=scc[ node[i].end ] ) { out[ scc[node[i].st] ] ++; in[ scc[node[i].end] ] ++; } } for( int i = 1 ; i<=sum ; i++ ) { if( !in[i] ) inMax ++; if( !out[i] ) outMax ++; } if( sum==1 ) cout << "0" << endl; else cout << max( inMax , outMax ) << endl; } return 0; }
View Code
因为 这里的数组要开的TM的实在是太多了 所以我用了 (n)*sizeof(int)来初始化 我测了下 节约了15ms....
today:
后来我终于知道
它并不是我的花
我只是恰好途径了它的盛放
相关文章推荐
- hdu 3836 Equivalent Sets(tarjan+缩点)
- HDU 3836 Equivalent Sets(Tarjan+缩点)
- HDU 3836 Equivalent Sets【Tarjan染色+搭桥】
- hdu 3836 Equivalent Sets (tarjan缩点)
- Strongly connected HDU - 4635(Tarjan+缩点)
- HDU 3836 Equivalent Sets(强连通+缩点,tarjan)
- hdu 3836 Equivalent Sets 强联通 tarjan缩点
- HDU 3836 tarjan求强连通分量
- [tarjan] hdu 3836 Equivalent Sets
- HDU 3836 Equivalent Sets(tarjan + 压缩强连通)
- HDU 3836 Equivalent Sets (tarjan求强联通分量)
- hdu 3836 Equivalent Sets(强连通,tarjan,4级)
- [tarjan] hdu 3836 Equivalent Sets
- hdu 3836 Equivalent Sets(强连通,tarjan,4级)
- HDU 3836 Equivalent Sets(强连通分量 Tarjan缩点)
- hdu 4635 Strongly connected (Tarjan+缩点)
- hdu 2586 tarjan 板子
- hdu 4612 Warm up(无向图Tarjan+树的直径)
- HDU 2586 How far away ?(Tarjan离线算法)
- 【tarjan缩点】hdu 3072