tarjan

来源:互联网 发布:马鞍山网络大学专升本 编辑:程序博客网 时间:2024/05/29 16:11

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  后三题用到“缩点”

原创粉丝点击