bzoj 1050 [HAOI2006]旅行comf [最小生成树] [动点spfa] [LCT]

原创 2016年08月30日 17:05:35

1050: [HAOI2006]旅行comf

Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 2740 Solved: 1486

Description

  给你一个无向图,N(N<=500)个顶点, M(M<=5000)条边,每条边有一个权值Vi(Vi<30000)。给你两个顶点S和T
,求一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出
这个比值,如果需要,表示成一个既约分数。 备注: 两个顶点之间可能有多条路径。

Input

  第一行包含两个正整数,N和M。下来的M行每行包含三个正整数:x,y和v。表示景点x到景点y之间有一条双向
公路,车辆必须以速度v在该公路上行驶。最后一行包含两个正整数s,t,表示想知道从景点s到景点t最大最小速
度比最小的路径。s和t不可能相同。
1

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<vector>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<string>
#include<iomanip>
#include<ctime>
#include<climits>
#include<cctype>
#include<algorithm>
#ifdef WIN32
#define AUTO "%I64d"
#else
#define AUTO "%lld"
#endif
using namespace std;
#define smax(x,tmp) x=max((x),(tmp))
#define smin(x,tmp) x=min((x),(tmp))
#define maxx(x1,x2,x3) max(max(x1,x2),x3)
#define minn(x1,x2,x3) min(min(x1,x2),x3)
typedef long long LL;
const int INF=0x3f3f3f3f;
const int maxn = 505;
const int maxm = 5005;
LL gcd(LL a,LL b)
{
    if(!b) return a;
    return gcd(b,a%b);
}
struct Fraction
{
    LL numer,deno; // numerator/denominator
    void reduce()
    {
        LL GCD = gcd(numer,deno);
        numer/=GCD; deno/=GCD;
    }
    Fraction (const LL a,const LL b) { numer=a,deno=b; reduce();  }
    bool operator < (const Fraction t) const
    {
        LL GCD=gcd(deno,t.deno);
        LL a1=numer*t.deno/GCD;
        LL a2=t.numer*deno/GCD;
        return a1 < a2;
    }
    bool operator == (Fraction t)
    {
        reduce(); t.reduce();
        return numer==t.numer && deno==t.deno;
    }
};
struct Edge
{
    int to,next;
    int val;
}edge[maxm<<1];
int head[maxn];
int maxedge;
inline void addedge(int u,int v,int c)
{
    edge[++maxedge] = (Edge) { v,head[u],c };
    head[u] = maxedge;
    edge[++maxedge] = (Edge) { u,head[v],c };
    head[v] = maxedge;
}
struct Road
{
    int u,v;
    int c;
    bool operator < (const Road t) const { return c > t.c; }
}road[maxm];
int n,m,S,T;
inline void init()
{
    scanf("%d%d",&n,&m);
    memset(head,-1,sizeof(head));
    maxedge=-1;
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&road[i].u,&road[i].v,&road[i].c);
    sort(road+1,road+m+1); //decending order
    scanf("%d%d",&S,&T);
}
queue <int> que;
bool inque[maxn];
int dis[maxn];
void spfa()
{
    while(!que.empty())
    {
        int u=que.front();que.pop();inque[u]=false;
        for(int i=head[u];~i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dis[v]>max(dis[u],edge[i].val))
            {
                dis[v]=max(dis[u],edge[i].val);
                if(inque[v]) continue;
                inque[v]=true;
                que.push(v);
            }
        }
    }
}
Fraction work()
{
    Fraction ans=Fraction(INF,1);
    memset(dis,0x3f,sizeof(dis));
    memset(inque,0,sizeof(inque));
    dis[S]=0;
    for(int i=1;i<=m;i++)
    {
        addedge(road[i].u,road[i].v,road[i].c);
        que.push(road[i].u); que.push(road[i].v);
        spfa();
        smin(ans,dis[T]<INF?Fraction(dis[T],road[i].c):Fraction(INF,1));
    }
    return ans;
}
void print(Fraction t)
{
    printf("%d",t.numer);
    if(t.deno^1ll) printf("/%d",t.deno);
    putchar('\n');
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("comf.in","r",stdin);
    freopen("comf.out","w",stdout);
#endif
    init();
    Fraction ans=work();
    if(ans==Fraction(INF,1)) puts("IMPOSSIBLE");
    else print(ans);
    return 0;
}
版权声明:S'il vous plait.

BZOJ1050 [HAOI2006]旅行comf(Kruskal算法)

SPFA是错误的:局部最优不能保证全局最优,因为要求的是比例最小  可以设计m^2的算法: 先将边按长度排序,然后限定最小边的长度w[i],依次加入更大的边, 当加到某条边w[j]后s与t连通(并查...
  • cjk_cjk
  • cjk_cjk
  • 2015年02月04日 02:26
  • 1465

[BZOJ1050][HAOI2006]旅行comf(并查集)

那些辗转反侧的夜晚,在某人的梦中,或许有着你未演完的情节。
  • Clove_unique
  • Clove_unique
  • 2016年09月21日 19:11
  • 657

BZOJ 1050 HAOI2006 旅行comf 动点SPFA

题目大意:给定一个无向图,每条边上有权值,求起点到终点的路径中最长边和最短边的最小比值 随手点开一道居然是动点SPFA的裸题…… 魔法森林都切了这个问题就不大了 我们把边权排序,从大到小加进这个图...
  • PoPoQQQ
  • PoPoQQQ
  • 2014年10月30日 14:21
  • 1543

BZOJ 1050: [HAOI2006]旅行comf|动点spfa

用Kruscal和并查集做似乎很显然,动点spfa似乎也是裸题。 按边权把边从大到小排序,枚举不断加边,将当前边的两端点入队spfa,不断更新mn数组(在当前边的情况下从起点到每一个点所经过的最大边...
  • ws_yzy
  • ws_yzy
  • 2016年02月15日 09:26
  • 456

[BZOJ]1050: [HAOI2006]旅行comf SPFA

Description   给你一个无向图,N(N ,求一条路径,使得路径上最大边和最小边的比值最小。如果S和T之间没有路径,输出”IMPOSSIBLE”,否则输出 这个比值,如果需要,表示...
  • baidu_36797646
  • baidu_36797646
  • 2017年01月04日 13:48
  • 315

bzoj 1050: [HAOI2006]旅行comf(最小生成树+并查集)

1050: [HAOI2006]旅行comf Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 2405  Solved: 1282 [Submi...
  • clover_hxy
  • clover_hxy
  • 2016年05月06日 16:38
  • 619

bzoj 1050 [HAOI2006]旅行comf (最小生成树)

Description给你一个无向图,N(N
  • u010379542
  • u010379542
  • 2017年10月13日 12:11
  • 57

【bzoj 1050】 [HAOI2006]旅行comf

老实说,这好像是我第3次写这道题了(各种原因),可还是WA了几发,边权从大到小排序以后,以每一个边为起点向后面并查集连边,第一次s和t联通的时候就是比值最小的时候,直接退出就可以了,然后用double...
  • pbihao
  • pbihao
  • 2016年10月11日 22:01
  • 106

BZOJ 1050 [HAOI2006]旅行comf

排序+贪心按边权排序,枚举权值最小边,贪心地从小到大选取比最小边大的边,用并查集维护连通性#include #include #define M 5005 #define N 505 using na...
  • ziqian2000
  • ziqian2000
  • 2016年09月25日 13:35
  • 178

【BZOJ 1050】 [HAOI2006]旅行comf

对kruscal的变形~ kruscal运用到路径问题中~ 详细题解~
  • Regina8023
  • Regina8023
  • 2015年01月31日 23:16
  • 1049
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:bzoj 1050 [HAOI2006]旅行comf [最小生成树] [动点spfa] [LCT]
举报原因:
原因补充:

(最多只允许输入30个字)