zoukankan      html  css  js  c++  java
  • POJ 1797 【一种叫做最大生成树的很有趣的贪心】【也可以用dij的变形思想~】

    题意:

    给一个无向图,找1到n所有的路中每条路最小权值的最大值!

    屌丝一开始的思想是利用dij的变形~

    但是==屌丝忘记了更新dis数组~结果TLE无数次...

    说正经的~dij的变形思想是这样的if(dis[now]<min(dis[pos],w[pos][now]))则更新dis[now]....这种变形的证明和原来dij的证明是一样的~大家自己脑补啊~

    heap优化的dij用时250ms~

    上代码~

    恶心的是不知道邻接表要搞多少边~这里RE无数次==

    #include<stdio.h>
    #include<string.h>
    #include<queue>
    using namespace std;
    int min(int a,int b)
    {
        if(a<b)
            return a;
        return b;
    }
    struct st
    {
        int w,id;
        st(int a,int b){w=a;id=b;}
        st(){}
    };
    struct cmp
    {
        bool operator()(const st &a,const st &b)
        {
            return a.w<b.w;
        }
    };
    int n,m;
    const int inf=99999999;
    int dis[1005];
    struct edge
    {
        int id,w;
        edge *next;
    };
    edge *adj[1005];
    edge edges[100005];
    int ednum;
    inline void addEdge(int a,int b,int c)
    {
        edge *aa;
        aa=&edges[ednum];
        ednum++;
        aa->id=b;
        aa->w=c;
        aa->next=adj[a];
        adj[a]=aa;
    }
    int solve()
    {
        for(int i=1; i<=n; i++)
        {
            dis[i]=-1;
        }
        dis[1]=inf;
        st tmp;
        priority_queue<st,vector<st>,cmp>q;
        q.push(st(inf,1));
        while(!q.empty())
        {
            tmp=q.top();
            q.pop();
            if(tmp.id==n)
                return tmp.w;
            for(edge *p=adj[tmp.id];p;p=p->next)
            {
                if(dis[p->id]<min(dis[tmp.id],p->w))
                {
                    dis[p->id]=min(dis[tmp.id],p->w);
                    q.push(st(dis[p->id],p->id));
                }
            }
        }
    }
    int main()
    {
        int t,a,b,c;
        scanf("%d",&t);
        for(int tt=1; tt<=t; tt++)
        {
            scanf("%d%d",&n,&m);
            ednum=0;
            for(int i=1; i<=n; i++)
                adj[i]=NULL;
            for(int i=1; i<=m; i++)
            {
                scanf("%d%d%d",&a,&b,&c);
                addEdge(a,b,c);
                addEdge(b,a,c);
            }
            printf("Scenario #%d:
    %d
    ",tt,solve());
            if(tt!=t)
                printf("
    ");
        }
    }

    接下来是最大生成树的思想~

    采用把边从大到小排序的思想,然后用并查集实现的方法~

    每次加入边之后确认1和n的连通情况~当第一次实现两者连通之后就输出那条边的权值~

    证明也是贪心的思想~大家自己脑补~

    时间稍慢 344ms

    上代码~

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    const int inf=1999999999;
    int n,m;
    bool ok;
    int rel;
    int min(int a,int b)
    {
        if(a<b)
            return a;
        return b;
    }
    struct edge
    {
        int st,ed,w;
    };
    int me[1005];
    edge edges[100005];
    bool cmp(edge a,edge b)
    {
        return a.w>b.w;
    }
    int findme(int a)
    {
        if(a!=me[a])
            return me[a]=findme(me[a]);
        return a;
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        for(int tt=1;tt<=t;tt++)
        {
            ok=0;
            scanf("%d%d",&n,&m);
            for(int i=1;i<=n;i++)
            {
                me[i]=i;
            }
            for(int i=0;i<m;i++)
            {
                scanf("%d%d%d",&edges[i].st,&edges[i].ed,&edges[i].w);
            }
            sort(edges,edges+m,cmp);
            for(int i=0;i<m;i++)
            {
                int tmpa=findme(edges[i].st);
                int tmpb=findme(edges[i].ed);
                if(tmpa!=tmpb)
                {
                    me[tmpb]=tmpa;
                }
                tmpa=findme(1);
                tmpb=findme(n);
                if(tmpa==tmpb)
                {
                    rel=edges[i].w;
                    break;
                }
            }
            printf("Scenario #%d:
    %d
    ",tt,rel);
            if(tt!=t)
                printf("
    ");
        }
        return 0;
    }
  • 相关阅读:
    python将阿拉伯数字转换为中文书写的数字形式
    python生成textgrid文件
    将 Nodejs 服务部署到阿里云服务器
    盛最多水的容器
    连续子数组的最大和
    数组中出现次数超过一半的数字
    变态跳台阶
    二进制中 1 的个数
    784.字母大小写全排列
    链表中环的入口节点
  • 原文地址:https://www.cnblogs.com/tun117/p/4830125.html
Copyright © 2011-2022 走看看