POJ 1679 浅谈不严格次小生成树

POJ 1679 浅谈不严格次小生成树_第1张图片
世界真的很大
今天狂刷了好多题,算是图论的一个小小阶段总结吧
其他题实在是有点水,算是复习了一下二分图的性质,但主要目的还是练板子
就由这道题(或是下一道,或者下下)来终结图论的复习吧!
毕竟NOIP已经不远了,越来越有要退赛的预感

看题先:

description:

给定一张图,判断其最小生成树是否唯一

input:

The first line contains a single integer t (1 <= t <= 20), the number of test cases. Each case represents a graph. It begins with a line containing two integers n and m (1 <= n <= 100), the number of nodes and edges. Each of the following m lines contains a triple (xi, yi, wi), indicating that xi and yi are connected by an edge with weight = wi. For any two nodes, there is at most one edge connecting them.

output:

For each input, if the MST is unique, print the total cost of it, or otherwise print the string ‘Not Unique!’.

参考这道题:BZOJ 1977
然后这道题就是水题了
直接判一下最小生成树链上的最大值有没有等于没有选上的这条边的值的
如果有,那么就说明最小生成树不唯一,反之则唯一
一遍Kruscal,一遍lca搞定
纪念1A

完整代码:

#include
#include
#include
using namespace std;

const int INF=0x3f3f3f3f;

struct edge
{
    int u,v,w,last;
}ed[10010],ad[10010];

int n,m,T,ans=0,bns=INF,tot=0,num=0;
int head[1010],dep[1010],st[1010][20],anc[1010][20];
int fa[1010],used[10010];

void add(int u,int v,int w)
{
    num++;
    ed[num].u=u;
    ed[num].v=v;
    ed[num].w=w;
    ed[num].last=head[u];
    head[u]=num;
}

int getfather(int x)
{
    if(x==fa[x]) return x;
    return fa[x]=getfather(fa[x]);
}

bool cmp(const edge &a,const edge &b)
{
    return a.wvoid Kruscal()
{
    sort(ad+1,ad+m+1,cmp);
    for(int i=1;i<=n;i++) fa[i]=i;
    for(int i=1;i<=m;i++)
    {
        int x=getfather(ad[i].u),y=getfather(ad[i].v);
        if(x!=y)
        {
            tot++,fa[x]=y,ans+=ad[i].w,used[i]=1;
            add(ad[i].u,ad[i].v,ad[i].w),add(ad[i].v,ad[i].u,ad[i].w);
        }
        if(tot==n-1) break ;
    }
}

void dfs(int u,int f)
{
    anc[u][0]=f;
    for(int i=1;i<=18;i++)
        anc[u][i]=anc[anc[u][i-1]][i-1],
        st[u][i]=max(st[u][i-1],st[anc[u][i-1]][i-1]);
    for(int i=head[u];i;i=ed[i].last)
    {
        int v=ed[i].v;
        if(v==f) continue ;
        dep[v]=dep[u]+1,st[v][0]=ed[i].w;
        dfs(v,u);
    }
}

int lca(int u,int v)
{
    int rt=0;
    if(dep[u]for(int i=18;i>=0;i--)
        if(dep[anc[u][i]]>=dep[v])
            rt=max(rt,st[u][i]),u=anc[u][i];
    if(u==v) return rt;
    for(int i=18;i>=0;i--)
        if(anc[u][i]!=anc[v][i])
            rt=max(rt,max(st[u][i],st[v][i])),u=anc[u][i],v=anc[v][i];
    return max(rt,max(anc[u][0],anc[v][0]));
}

void init()
{
    memset(head,0,sizeof(head));
    memset(fa,0,sizeof(fa));
    memset(dep,0,sizeof(dep));
    memset(st,0,sizeof(st));
    memset(anc,0,sizeof(anc));
    memset(used,0,sizeof(used));
    num=ans=tot=0;
    bns=INF;
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
            scanf("%d%d%d",&ad[i].u,&ad[i].v,&ad[i].w);
        Kruscal();
        dfs(1,1);
        for(int i=1;i<=m;i++)
        {
            if(used[i]) continue ;
            int u=ad[i].u,v=ad[i].v;
            bns=min(bns,ad[i].w-lca(u,v));
        }
        if(bns) printf("%d\n",ans);
        else printf("Not Unique!\n");
    }
    return 0;
}
/*
Whoso pulleth out this sword from this stone and anvil is duly born King of all England
*/

嗯,就是这样

你可能感兴趣的:(最小生成树c++)