您的位置:首页 > 其它

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

如果是这样的情况

#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:

  后来我终于知道

  它并不是我的花

  我只是恰好途径了它的盛放
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: