(最短路)【UVA - 11090 】Going in Cycle!!

题目链接:https://vjudge.net/problem/UVA-11090

n个点m条边的加权有向图,求权值最小的回路。

看了白书才明白是二分寻找答案,让我自己想肯定想不到。每条边的权值减去mid值,判断是否形成负权回路即可。写了两种写法,不是很喜欢集合在结构体里面…不过封装确实简洁很多。第一种是队列,第二种直接循环。

今天下午队伍一起打了个训练赛,写去年乌鲁木齐的题目,签到完就写不了第三题了。。不过最近确实状态也不好,脑子也转不过来,顶多充当翻译员。希望去青岛的时候竞技状态能好一点,虽然是Latte队伍!

最后恭喜IG!

/*
* @Author: SamsonHo
* @Date:   2018-10-26-16.11.25
* @URL:https://vjudge.net/problem/UVA-11090
*/
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int MAXN = 1e4+10;

struct Edge
{
    int from,to;
    double val;
    Edge(int from,int to,double val):from(from),to(to),val(val) {}
};

vector<Edge> edges;
vector<int> g[MAXN];
int n,m,cnt[MAXN],inque[MAXN];
double d[MAXN];
bool Bellman_Ford()
{
    queue<int> que;
    for(int i = 1; i <= n; ++i)
    {
        d[i] = 0;
        cnt[i] = 0;
        que.push(i);
    }
    inque[1] = 1;
    while(!que.empty())
    {
        int u = que.front();
        que.pop();
        inque[u] = 0;
        int len = g[u].size();
        for(int i = 0; i < len; ++i)
        {
            Edge& e = edges[g[u][i]];
            if(d[e.to] > d[e.from]+e.val)
            {
                d[e.to] = d[e.from]+e.val;
                if(!inque[e.to])
                {
                    que.push(e.to);
                    inque[e.to] = 1;
                    if(++cnt[e.to] > n) return true;
                }
            }
        }
    }
    return false;
}

bool test(double x)
{
    for(int i = 0; i < m; ++i)
        edges[i].val -= x;
    bool ret = Bellman_Ford();
    for(int i = 0; i < m; ++i)
        edges[i].val += x;
    return ret;
}

int main(void)
{
    int T,kase = 0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i = 0; i <= n; ++i)
            g[i].clear();
        edges.clear();
        int u,v,Max = 0;
        double w;
        for(int i = 0; i < m; ++i)
        {
            scanf("%d%d%lf",&u,&v,&w);
            if(w > Max) Max = w;
            edges.push_back(Edge(u,v,w));
            g[u].push_back(i);
        }
        printf("Case #%d: ",++kase);
        if(!test(Max+1))
            puts("No cycle found.");
        else
        {
            double l = 0,r = Max;
            while(r - l > 1e-3)
            {
                double m = l+(r-l)/2.0;
                if(test(m)) r = m;
                else    l = m;
            }
            printf("%.2lf\n",l);
        }
    }
}

 

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
const int MAXN = 1e4+10;

struct Edge
{
    int from,to;
    double val;
    Edge(int from,int to,double val):from(from),to(to),val(val) {}
};

vector<Edge> edges;
vector<int> g[MAXN];
int n,m,cnt[MAXN],inque[MAXN],num;
double d[MAXN];

bool Bellman_Ford(int s)
{
    for(int i = 0; i <= n; ++i) d[i] = INF;
    d[s] = 0;
    for(int i = 0; i < n-1; ++i)
    {
        for(int j = 0; j < m; ++j)
        {
            if(d[edges[j].to] > d[edges[j].from] + edges[j].val)
                d[edges[j].to] = d[edges[j].from] + edges[j].val;
        }
    }
    for(int i = 0; i < m; ++i)
    {
        if(d[edges[i].to] > d[edges[i].from] + edges[i].val)
            return true;
    }
    return false;
}

bool test(double x)
{
    for(int i = 0; i < m; ++i)
        edges[i].val -= x;
    bool ret = Bellman_Ford(1);
    for(int i = 0; i < m; ++i)
        edges[i].val += x;
    return ret;
}

int main(void)
{
    int T,kase = 0;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i = 0; i <= n; ++i)
            g[i].clear();
        edges.clear();
        int u,v,Max = 0;
        double w;
        for(int i = 0; i < m; ++i)
        {
            scanf("%d%d%lf",&u,&v,&w);
            if(w > Max) Max = w;
            edges.push_back(Edge(u,v,w));
            g[u].push_back(i);
        }
        printf("Case #%d: ",++kase);
        if(!test(Max+1))
            puts("No cycle found.");
        else
        {
            double l = 0,r = Max;
            while(r - l > 1e-3)
            {
                double m = l+(r-l)/2.0;
                if(test(m)) r = m;
                else    l = m;
            }
            printf("%.2lf\n",l);
        }
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值