hdu1598

题意:n个城市m条路,每条路上开车有个速度,要你求从start到end最高速度与最低速度的最小之差;

给出两种求得方法第二种有问题

代码1:用并查集枚举高度差,其实这里是去掉一部分边,然后跑克鲁斯卡尔。思路写在代码注释上

/*
  题意:输入n和m 然后m条边,u v a 表示u到v这条路上的速度是a。要你求 输入从start到end
  最快速度与最慢速度相差最小的差。
思路:先将边排序,然后去掉一些边,再跑克鲁斯卡尔,边跑的时候变判断start点和end点在不在同一个连通模块,
如果在的话,就不用继续克鲁斯卡尔了,因为在往后面最大的边一直增大,所以差值也变大。然后从小到大去掉边,
最后找一个最小的差值。
  
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<algorithm>
#include<vector>
using namespace std;
struct edge{
int from,to,w;
};
int n,m;
vector<edge>edges;
int pre[210];
bool cmp(edge a,edge b)
{
    return a.w<b.w;
}
void addedge(int x,int y,int w)
{
    edge v={x,y,w};
    edges.push_back(v);
}
int find(int x)
{
    if(pre[x]==x)
    {
        return x;
    }
    else
    {
        pre[x]=find(pre[x]);
        return pre[x];
    }
}
int kluska(int start,int end1)
{

    int ans=999999999;
    for(int i=0;i<edges.size();i++)
    {    for(int i=1;i<=n;i++)
          {
           pre[i]=i;
          }
        for(int j=i;j<edges.size();j++)
        {   edge v=edges[j];
            int f1=find(v.from);
            int f2=find(v.to);
            if(f1!=f2)
            {
                pre[f2]=f1;
            }
            if(find(start)==find(end1))
            {
                if(ans>v.w-edges[i].w)
                {
                    ans=v.w-edges[i].w;
                }
                break;
            }
        }
    }
    if(ans==999999999)
    {
        printf("-1\n");
    }
    else printf("%d\n",ans);
}
int main()
{
    while(scanf("%d %d",&n,&m)!=EOF)
    {   edges.clear();
        for(int i=1;i<=m;i++)
        {
            int x,y,w;
            scanf("%d %d %d",&x,&y,&w);
            addedge(x,y,w);
        }
        int q;
        scanf("%d",&q);
        int start,end1;
        sort(edges.begin(),edges.end(),cmp);
        for(int i=1;i<=q;i++)
        {
            scanf("%d %d",&start,&end1);
            kluska(start,end1);
        }
    }
}

代码二:二分高度差加最短路

/*
这种思路是,二分枚举高度差,然后跑最短路,但是这种方法是有问题的,hud没有测出来。
mid 就是高度差,然后枚举边求得最小高度,和最大高度,然后跑最短路的时候假如这两个条件的限制即可。
这组数据用着种方法做就有问题

3 2
1 2 3
2 3 10
1
1 3
这里的答案为-1
但是正确的答案为7
但杭电测不出

*/
#include <iostream>
#include <algorithm>
#include <queue>
#include<stdio.h>
using namespace std;
#define inf 0x3fffffff
#define M 205                   //最大点数

struct son{
    int v, w;
};
vector<son> g[M];
bool inq[M];                    //入队列标记
int dist[M], tp[1005], n;       //n:实际点数

void init ()
{
    for (int i = 1; i <= n; i++)
        g[i].clear();
}

bool spfa (int u, int low, int high, int t)
{
    int i, v, w;
    for (i = 1; i <= n; i++)
    {
        dist[i] = inf;
        inq[i] = false;
    }
    queue<int> q;
    q.push (u);
    inq[u] = true;
    dist[u] = 0;
    while (!q.empty())
    {
        u = q.front();
        q.pop();
        inq[u] = false;
        for (i = 0; i < g[u].size(); i++)
        {
            v = g[u][i].v;
            w = g[u][i].w;
            if (w < low || w > high)  //限制条件
                continue;
            if (dist[u] + w < dist[v])
            {
                if (v == t)             //可以到达终点返回true
                    return true;
                dist[v] = dist[u] + w;
                if (!inq[v])
                {
                    q.push (v);
                    inq[v] = true;
                }
            }
        }
    }
    return false;
}

int main()
{
    bool flag;
    int m, u, v, i, l, r, mid, maxs;
    son x;
    while (~scanf ("%d%d", &n, &m))
    {
        init();
        maxs = 0;
        for (i = 0; i < m; i++)
        {
            scanf ("%d%d%d", &u, &v, tp+i);
            if (maxs < tp[i])
                maxs = tp[i];
            x.v = v, x.w = tp[i];
            g[u].push_back (x);
            x.v = u;
            g[v].push_back (x);
        }
        sort (tp, tp+m);    //边的权值从小到大排序
        int q;
        scanf ("%d", &q);
        while (q--)
        {
            scanf ("%d%d", &u, &v);
            l = 0, r = maxs;
            int ans = -1;
            while (l <= r)   //二分枚举舒适度差
            {
                flag = false;
                mid = (l+r) >> 1; //mid就是差

                for (i = 0; tp[i] + mid <= maxs; i++)
                {
                    if (spfa (u, tp[i], tp[i]+mid, v))
                    {
                        flag = true;
                        break;
                    }
                }
                if (flag)
                    ans = mid, r = mid - 1;
                else l = mid + 1;
            }
            printf ("%d\n", ans);
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值