ACM模版——图论

//===========================================\\

|    邻接表                                  |

\\===========================================//

struct node { int num,d; node *next; }*head[1010],*v;

void input(int a,int b,int c)

{

    v=new node;

    v->num=b;

    v->d=c;

    v->next=head[a];

    head[a]=v;

}  //不同组数据,记得要初始化head[i]=NULL

//===========================================\\

|    Dijkstra 算法                             |

\\===========================================//

int cov[1010],dis[1010],path[1010],n;

const int INF=10000;

void dj(int s,int t) // 源s,目标t

{

int i,min,k=s;

memset(cov,0,sizeof(cov));

cov[k]=1;

for (int i=1; i<=n; i++) dis[i]=INF;

path[k]=-1;

dis[k]=0;

while ( !cov[t] ) // 或for(i=1; i<n; i++)

{

      for ( v=head[k]; v!=NULL; v=v->next)

       if ( !cov[v->num] && dis[v->num]>dis[k]+v->d )

         {

            dis[v->num]=dis[k]+v->d;

            path[v->num]=k;

         }

     for (i=1,min=INF; i<=n; i++ )

if ( !cov[i] && dis[i]<min )

       {

min=dis[i];

           k=i;

}

      cov[k]=1;

}

}

//===========================================\\

|    SPFA算法                                |

\\===========================================//

int dis[1010],path[1010],clu[1010],n;

bool cov[1010]; //判断是否入队

bool spfa(int s)

{

    int i;

    queue<int> q;

    q.push(s);

    memset(clu,0,sizeof(clu));

    clu[s]++;

    memset(cov,0,sizeof(cov));

    path[s]=-1;

    for (i=1; i<=n; i++) dis[i]=INF;

    dis[s]=0;

    while ( !q.empty() )

    {

        i=q.front();

        q.pop();

        for ( v=head[i]; v!=NULL; v=v->next )

            if ( dis[v->num]>dis[i]+v->d )

            {

                dis[v->num]=dis[i]+v->d;

                path[v->num]=i;

                if ( !cov[v->num])

                {

                    clu[v->num]++;

                    if ( clu[v->num]>n ) return 0;

                    cov[v->num]=1;

                    q.push(v->num);

                }

            }

    }

    return true;

}

//===========================================\\

|    Floyd算法                               |

\\===========================================//

int dis[1010][1010],n,path[1010];

void Floyd()

{

int i,j,k;

for (i=1; i<=n; i++) dis[i][i]=0;

for (k=1; k<=n; k++)

    for (i=1; i<=n; i++)

     for (j=1; j<=n; j++)

      if ( dis[i][k]<INF && dis[k][j]<INF  && dis[i][j]<dis[i][k]+dis[k][j] )

      {

          path[i][j]=k;

          dis[i][j]=dis[i][k]+dis[k][j];   

       }

}

//===========================================\\

|    二分图                                |

\\===========================================//

//最小覆盖点数(所有边与这些点关联)=最大匹配数

//最大独立集点数(任意两点不相连)=节点数-最大匹配数

//最小路径覆盖数=原图节点数-最大匹配数(有向无环图)

Ps:最小覆盖点数,最大独立点数是针对二分图说的

常见建图模型:

1、  行列匹配法(1):“行”为x集,“列”为y集

2、  方阵染色法(1)

3、  反建法(2)

4、  拆点法(3):若i->j存在,建边i->j’

//===========================================\\

|    Hungary 算法                            |

\\===========================================//

bool cov[510]; //在每次找增广路时,判断点是否到达过

int x[510],y[510]; //记录与哪点相匹配,若未匹配为-1

int k,m,n;

bool sb(int a) //找增广路

{

    node *p;

    for ( p=head[a]; p!=NULL; p=p->next)

    {

        if ( !cov[p->num] )

        {

            cov[p->num]=true;

            if ( y[p->num]==-1 || sb(y[p->num]) )

            {

                x[a]=p->num;

                y[p->num]=a;

                return true;

            }

        }

    }

    return false;

}

int hungary()

{

    int i,ans=0;

    memset(x,0xff,sizeof(x));

    memset(y,0xff,sizeof(y));

    for ( i=1; i<=m; i++ ) if ( x[i]==-1 )

    {

        memset(cov,false,sizeof(cov));

        if ( sb(i) ) ans++;

    }

    return ans;

}

//===========================================\\

|    Hopcroft Karp算法                        |

\\===========================================//

 

//===========================================\\

|    Kruskal 算法                             |

\\===========================================//

struct tmp { int x,y,cost; }road[5000];

bool cmp(tmp a,tmp b) { return a.cost<b.cost; }

int kru()

{

    int i=0,j=n-1,ans=0;

    for (int k=1; k<=n; k++) g[k]=r[k]=k; //并查集

    sort(road+1,road+n*(n-1)/2+1,cmp); //边升序排序

    while ( j )

    {

        i++;

        if ( g[road[i].x]!=g[road[i].y] )

        {

            ans+=road[i].cost;

            update(road[i].x,road[i].y); //并查集

            j--;

        }

    }

    return ans;   //返回最小总权值

}

//===========================================\\

|    Prim 算法                               |

\\===========================================//

int dis[1010],path[1010],n;

bool cov[1010];

int prim()

{

    int i,j,min,s=1,k,ans=0;

    memset(cov,0,sizeof(cov));

    cov[s]=1;

    for (i=1; i<=n; i++) dis[i]=INF;

    path[s]=-1;

    for (j=1; j<n; j++)

    {

        cov[s]=1;

        for (p=head[s]; p!=NULL; p=p->next)

            if ( !cov[p->num] && dis[p->num]>p->d )

            {

                dis[p->num]=p->d;

                path[p->num]=s;

            }

        for (i=1,min=INF; i<=n; i++)

            if ( !cov[i] && dis[i]<min )

            {

                min=dis[i];

                s=i;

            }

        ans+=min;

    }

    return ans;

}

//===========================================\\

|    拓扑排序                                |

\\===========================================//

int in[100010],s[100010],path[100010],n;

bool Toposort()    //path[i]记录i前一个点

{

    int i,j=0;

    queue<int> q;

    for ( i=1; i<=n; i++) if ( !in[i] )

    {

        q.push(i);

        path[i]=-1;

    }

    while ( !q.empty() )

    {

        s[++j]=q.front();

        q.pop();

        for (node *p=head[s[j]]; p!=NULL; p=p->next)

          if ( !--in[p->num] )

          {

              q.push(p->num);

              path[p->num]=s[j];

          }

    }

    if ( j<n ) return false;

    else return true;

}

posted @ 2012-09-22 13:50  枫落丹寒  阅读(121)  评论(0)    收藏  举报