[URAL1416 Confidential]

[关键字]:次小生成树

[题目大意]:求出给出图的最小和次小生成树。

//=============================================================================

[分析]:http://www.cppblog.com/MatoNo1/archive/2011/06/25/147627.html#149420讲的又清楚又详细,ORZMato大神!

[代码]:

kurscal
#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<cstring>

#include<algorithm>

using namespace std;



const int INF=1000000;

const int MAXN=1000;

const int MAXM=130000;



struct node

{

       int x,y,d,p,next,no;

}e[MAXM],E[MAXM+MAXM];

int n,m,M,ans1,ans2,tot,now=INF,h,t;

int f[MAXN],s[MAXN],nx[MAXN],q[MAXM];

bool cmp(node a,node b){return a.d<b.d;}



void Init_d()

{

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

         E[i].x=E[i].next=E[i].p=i;

     if (n&1) M=n+1; else M=n+2;

}



void Add(int x,int y,int z)

{

     E[M].x=x,E[M].y=y,E[M].d=z,E[M].p=E[x].p,E[M].next=x,E[x].p=M,E[E[M].p].next=M++;

     E[M].x=y,E[M].y=x,E[M].d=z,E[M].p=E[y].p,E[M].next=y,E[y].p=M,E[E[M].p].next=M++;

}



void Del(int NO)

{

     E[E[NO].p].next=E[NO].next,E[E[NO].next].p=E[NO].p;

     E[E[NO^1].p].next=E[NO^1].next,E[E[NO^1].next].p=E[NO^1].p;

}



void Init()

{

     scanf("%d%d",&n,&m);

     if (!m)

        if (n>1){ans1=ans2=INF;return;}

     Init_d();

     for (int i=1;i<=m;++i)

     {

         int x,y,z;

         scanf("%d%d%d",&x,&y,&z);

         e[i].no=M,Add(x,y,z);

         e[i].x=x,e[i].y=y,e[i].d=z;

     }

}



int GET(int v)

{

    if (f[v]<0) return v;

    f[v]=GET(f[v]);

    return f[v];

}



void Union(int r1,int r2,int NO,int l0)

{

     //printf("%d\n",NO);

     q[h=t=0]=r1;

     while (h<=t)

     {

           int u=q[h++];

           for (int i=s[u];i!=-1;i=nx[i])

               q[++t]=i;

     }

     for (int i=0;i<=t;++i)

     {

         int u=q[i];

         for (int j=E[u].next;j!=u;j=E[j].next)

         {

             int v=E[j].y;

             if (j!=NO && GET(v)==r2)

             {

                       int temp=E[j].d-l0;

                       if (temp<now) now=temp;//,printf("%d %d\n",j,NO);

                       Del(j);

             }

         }

     }

     f[r2]+=f[r1],f[r1]=r2,nx[r1]=s[r2],s[r2]=r1;

}



void Solve()

{

     for (int i=1;i<=n;++i) f[i]=s[i]=nx[i]=-1;

     sort(e+1,e+m+1,cmp);

     /*for (int i=1;i<=m;++i)

         printf("%d %d %d %d\n",e[i].x,e[i].y,e[i].d,e[i].no);*/

     for (int i=1;i<=m;++i)

     {

         int r1=GET(e[i].x),r2=GET(e[i].y);

         if (r1!=r2)

         {

                    //printf("%d %d %d %d %d\n",r1,r2,e[i].x,e[i].y,e[i].d);

                    ans1+=e[i].d,++tot;

                    //printf("%d\n",e[i].no);

                    if (f[r1]>=f[r2]) Union(r1,r2,e[i].no,e[i].d); else Union(r2,r1,e[i].no^1,e[i].d);

         }

     }

     //printf("%d\n",now);

     if (tot<n-1) ans1=ans2=INF;

     if (now==INF) ans2=INF; else ans2=ans1+now;

     if (ans1==INF) ans1=-1;if (ans2==INF)ans2=-1;

     printf("Cost: %d\nCost: %d\n",ans1,ans2);

}



int main()

{

    freopen("in.txt","r",stdin);

    freopen("out.txt","w",stdout);

    Init();  

    /*printf("%d\n",M);

    for (int i=1;i<=M;++i)

        printf("%d %d %d %d %d\n",E[i].x,E[i].y,E[i].d,E[i].p,E[i].next);

    for (int i=1;i<=m;++i)

        printf("%d %d %d %d\n",e[i].x,e[i].y,e[i].d,e[i].no);*/

    if (!ans1) Solve();

    return 0;

}
prim
#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<cstring>

#include<algorithm>

using namespace std;



const int INF=10000000;

const int MAXN=510;



int n,m,ans1,ans2,now;

int s[MAXN][MAXN],s2[MAXN][MAXN];

int f[MAXN][MAXN],d[MAXN],p[MAXN];

bool vis[MAXN];



void Init()

{

    scanf("%d%d",&n,&m);

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

    {

        p[i]=i;

        for (int j=1;j<=n;++j) s[i][j]=s2[i][j]=INF;

    }

    /*for (int i=1;i<=n;++i)

    {

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

            printf("%d ",s2[i][j]);

        printf("\n");

    }*/

    if (!m)

        if (n>1) {ans1=ans2=INF;return;}

    for (int i=1;i<=m;++i)

    {

        int x,y,z;

        scanf("%d%d%d",&x,&y,&z);

        if (z<s[x][y]) s2[x][y]=s2[y][x]=s[x][y],s[x][y]=s[y][x]=z; else 

        if (z<s2[x][y]) s2[x][y]=z;

        //printf("%d %d %d %d %d\n",x,y,z,s[x][y],s2[x][y]);

    }

    /*for (int i=1;i<=n;++i)

    {

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

            printf("%d ",s2[i][j]);

        printf("\n");

    }*/

}



void Solve()

{

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

        vis[i]=0,d[i]=INF;

    d[1]=0,now=INF;

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

    {

        int Min=INF,Minj;

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

            if (!vis[j] && Min>d[j]) Min=d[Minj=j];

        if (Min==INF) {ans1=ans2=INF;return;}

        vis[Minj]=1,ans1+=Min;

        s[p[Minj]][Minj]=s[Minj][p[Minj]]=INF;

        if (s2[p[Minj]][Minj]<INF && s2[p[Minj]][Min]-Min<now) now=s2[p[Minj]][Min]-Min;

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

            if (!vis[j] && d[j]>s[Minj][j]) d[j]=s[Minj][j],p[j]=Minj;

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

            if (vis[j] && j!=Minj) f[j][Minj]=f[Minj][j]=max(f[j][p[Minj]],Min);

        //printf("%d %d\n",Min,Minj);

    }

    //printf("%d\n",now);

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

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

            if (s[i][j]<INF)

            {

                int temp=s[i][j]-f[i][j];

                if (temp<now) now=temp;

            }

    if (now==INF) ans2=INF; else ans2=ans1+now;

    if (ans1==INF) ans1=-1; if (ans2==INF) ans2=-1;

    printf("Cost: %d\nCost: %d\n",ans1,ans2);

}



int main()

{

    freopen("in","r",stdin);

    freopen("out","w",stdout);

    Init();

    if (!ans2) Solve();

    return 0;

}

你可能感兴趣的:(conf)