1. 程式人生 > >UVA-10462 Is There A Second Way Left?

UVA-10462 Is There A Second Way Left?

給出圖,要求是否有生成樹,是否有次小生成樹,輸出次小生成樹花費

因為給出的圖有重邊,所以不能用prim求次小,改用kruskal

先用kruskal求出最小生成樹,並記錄所用邊

接下來列舉刪去所用邊,再生成一次最小生成樹,其中最小的就是次小生成樹

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int N=100+10;
const int M=200+10;
const int INF=0x7f7f7f7f;
struct Edge
{
    int u,v,w;
    bool operator < (const Edge &a) const
    {
        return w<a.w;
    }
}edge[M];
int tot;
void addedge(int u,int v,int w)
{
    edge[tot].u=u;
    edge[tot].v=v;
    edge[tot++].w=w;
}
int uf[N];
int find(int u)
{
    if(uf[u]==-1) return u;
    return uf[u]=find(uf[u]);
}
int used[N];
void solve(int n,int kase)
{
    printf("Case #%d : ",kase);
    int ans1=0;
    bool flag=false;
    sort(edge,edge+tot);
    memset(uf,-1,sizeof(uf));
    int cnt=0;
    for(int i=0;i<tot;i++)
    {
        int u=edge[i].u;
        int v=edge[i].v;
        int w=edge[i].w;
        int ru=find(u);
        int rv=find(v);
        if(ru!=rv)
        {
            ans1+=w;
            used[cnt]=i;
            cnt++;
            uf[ru]=rv;
            if(cnt==n-1)
            {
                flag=true;
                break;
            }
        }
    }
    if(!flag&&n>1)
    {
        printf("No way\n");
        return;
    }
    int ans2=INF;
    for(int k=0;k<n-1;k++)
    {
        cnt=0;
        int t=0;
        flag=false;
        memset(uf,-1,sizeof(uf));
        for(int i=0;i<tot;i++)
        {
            if(i==used[k]) continue;
            int u=edge[i].u;
            int v=edge[i].v;
            int w=edge[i].w;
            int ru=find(u);
            int rv=find(v);
            if(ru!=rv)
            {
                t+=w;
                cnt++;
                uf[ru]=rv;
                if(cnt==n-1)
                {
                    flag=true;
                    break;
                }
            }
        }
        if(flag) ans2=min(ans2,t);
    }
    if(ans2==INF) printf("No second way\n");
    else printf("%d\n",ans2);
}
int main()
{
    int T,kase=0;
    int n,m;
    int a,b,c;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        tot=0;
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            addedge(a,b,c);
        }
        solve(n,++kase);
    }
    return 0;
}