procedure2012
It's not worth it to know you're not worth it!

[关键字]:次小生成树

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

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

[分析]: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;
}
posted on 2012-04-14 00:50  procedure2012  阅读(176)  评论(0编辑  收藏  举报