struct edge {
int v , nex;
}e[maxm];
int k ,head[maxn];
void addedge(inta,int b) {
e[k].v = b;
e[k].nex = head[a];
head[a] = k++;
}//链式前向星
int dfn[maxn] ,low[maxn] , sta[maxn] , belon[maxn] , atype , top , times , vis[maxn];
//时间戳 low数组 栈数组 记录连通种类的数组 连通种类 栈下标 时间戳累加变量
void tarjan(int u){
int i , j;
dfn[u] = low[u] = times++;
sta[++top] = u;
vis[u] = true;
for (i = head[u] ; i ; i = e[i].nex) {
int v = e[i].v;
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u] ,low[v]);
} else if(vis[v])
low[u] = min(low[u] ,dfn[v]);
}
if (dfn[u] == low[u]) {
atype ++;
do {
j = sta[top--];
belon[j] = atype;
vis[j] = false;
}while(u!=j);
}
}
memset(head ~ dfn~ low ~ belon ~ sta ~ vis,0,sizeof(head));
k = 1 , times = 1, atype = 0;
for (i = 1 ~ n) if (!dfn[i]) tarjan(i);
缩点:就是“整理”连通分量 比如统计初度和入度为0的联通块
for (i = 1 ; i<= n ; i ++) {
int temp = belon[i];
for (j = head[i] ; j ; j =e[j].nex) {
intv = e[j].v;
int tmp = belon[v];
if(belon[i]!=belon[v]) {
out[temp] ++;
in[tmp] ++;
}
}
}
1、给定一张有向图,问最少添加几条边使得有向图成为一个强连通图。
思路:缩点后找出入度为0的点和初度为0的块,统计个数,选择大的个数输出。
2、有一张有向图,有一个消息需要传播到每个人,消息有传递性,每个人都有点权,求最小花费让消息传到每个人那里。
思路:缩点后找出入度为0(没得到消息的一些人)块,然后累加其中最小点权。
例题:hdu 1269 hdu 1827 hdu 2767 hdu3836 后三题用到“缩点”