zoukankan      html  css  js  c++  java
  • 小白_图论1 基础题

    小白_图论1    

    1、UVA 10034   最小生成树,水,墨水连点。

    2、UVA 10048   floyd,找最小的可行径上的最大边,水,忍受噪音。

    3、UVA 10397   最小生成树,题意:架设电缆,但有的点已经相连。  总结:已经相连的点,先连通或者直接标为0。Prim直接过了,但Kruskal一直RE,不知道哪错了。

    4、UVA 10369   最小生成树,题意:p个哨点相连,有卫星通道,求最大dis。  总结:题意有点纠结,s个卫星只能有s-1个卫星通道。所以就是第p-s条边。

    5、UVA 658     最短路,题意:好迷,查bug,有m个补丁,每个补丁两个字符串s1,s2,s1表示可以用这个补丁的条件,s2表示用后变化。  总结:状态表示成点,但这里好纠结。 不会

    6、UVA 10099   floyd,找最大的可行径上的最小边,G[i][j]=max(G[i][j], min(G[i][k],G[k][j])),水,旅游团带人。

    7、

    8、

    9、

    思路总结:

    /*
    Floyd  思路总结:
    有点像dp,对于G[i][j],介入一个点k(如果存在G[i][k],G[k][j]),
    然后在G[i][j]、G[i][k]、G[k][j]之间取最优值。
    但Floyd复杂度很高,只能处理范围小的情况
    */
    int n,m,G[N][N];
    void Floyd()
    {
        FF(k,1,n) FF(i,1,n) FF(j,1,n) {     // k要放在最外层
            G[i][j]=max(G[i][j], min(G[i][k],G[k][j]));
        }
    }
    Floyd
    /*
    Kruskal 思路总结
    然后把所有边按权值排序,遍历。如果这条边相连两点不是一个连通分量,
    就利用并查集,把这两点并成一个连通分量。
    */
    struct Edge
    {
        int u,v;
        double val;
        friend bool operator < (const Edge &a, const Edge &b) {
            return b.val>a.val;
        }
    }edge[N*N];
    int n,m,x[N],y[N];
    int tot,father[N];
    
    double Dis(int i,int j)
    {
        return sqrt( (x[i]-x[j])*(x[i]-x[j]) + (y[i]-y[j])*(y[i]-y[j]) );
    }
    void Addedge(int u,int v,double len)
    {
        edge[tot].u=u, edge[tot].v=v, edge [tot++].val=len;
    }
    int Find(int c)
    {
        int p=c,i=c,j;
        while(father[p]!=p)  p=father[p];
        while(father[i]!=p) {
            j=father[i], father[i]=p, i=j;
        }
        return p;
    }
    bool Unite(int u,int v)
    {
        int fau=Find(u), fav=Find(v);
        if(fau!=fav) { father[fav]=fau; return true; }
        return false;
    }
    double Kruskal()
    {
        double sum=0;
        int num=0;
        sort(edge,edge+tot);
        F(i,0,tot) {
            if(num>=n-1) break;
            if(Unite(edge[i].u,edge[i].v)) sum+=edge[i].val, num++;
        }
        return sum;
    }
    Kruskal
    /*
    Prim 思路总结:
    n个点分为两个集合U、R,U为已取的点,R为未取的点,先任意取一个点放入U中。
    取距离最小的U中点可以到达的R中点,放入U中,如此n-1遍。
    */
    int vis[N],G[N][N];
    double Prim()
    {
        double sum=0;
        vis[1]=1;
        FF(i,2,n) {   //循环n-1次即可
            double minn=M;
            int mi,mj;
            FF(i,1,n) if(vis[i]==1) {  //每次找出未取的距离最小的点
                FF(j,1,n) if(vis[j]==0) {
                    if(minn>G[i][j]) {
                        minn=G[i][j], mi=i, mj=j;
                    }
                }
            }
            sum+=G[mi][mj], vis[mj]=1;
        }
        return sum;
    }
    Prim
  • 相关阅读:
    按属性分割要素
    python os.path模块
    用数组显示裴波那契数列
    计算两位数的加减乘除
    输入一串数字统计0到9每个数字的个数
    开辟新空间输入成绩
    关系表达式、条件表达式、逻辑表达式
    变量、函数和程序控制
    哥德巴赫定理
    找出二维数组中最大的值
  • 原文地址:https://www.cnblogs.com/sbfhy/p/6240393.html
Copyright © 2011-2022 走看看