hdu1598

来源:互联网 发布:被冒名网络贷款 编辑:程序博客网 时间:2024/06/05 00:15

题意: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 21 2 32 3 1011 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;}


原创粉丝点击