UVA 558 判断负环

本文介绍了处理带负权边的单源最短路径问题的两种算法:Bellman-Ford算法和SPFA算法(Shortest Path Faster Algorithm)。Bellman-Ford算法通过多次松弛操作找出最短路径,而SPFA算法则利用队列进行改进,提高了效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        边上带有负值的单源最短路径。

Bellman-Ford算法:


#include<cstdio>
#include<cstring>
#include<iostream>
#define MAXN 2000+5
#define INF 1000000
using namespace std;
int u[MAXN],v[MAXN],w[MAXN],n,m,d[1005];
int main()
{
//    freopen("in.txt","r",stdin);
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d%d",&n,&m);
        for(int i=0;i<m;i++)
            scanf("%d%d%d",&u[i],&v[i],&w[i]);
        for(int i=0;i<n;i++)
            d[i]=INF;
        d[0]=0;
        for(int k=0;k<n-1;k++)
        {
            for(int i=0;i<m;i++)
            {
                int x=u[i],y=v[i];
                if(d[x]<INF)  d[y]=min(d[y],d[x]+w[i]);
            }
        }
        bool ok=false;
        for(int i=0;i<m;i++)
        {
            int x=u[i],y=v[i];
            if(d[x]<INF&&d[y]>d[x]+w[i])
                {
                    ok=true;
                    puts("possible");
                    break;
                }
        }
        if(!ok)
            puts("not possible");
    }
    return 0;
}

SPFA算法(邻接表):

#include<cstdio>
#include<cstring>
#include<queue>
#include<iostream>
#define MAXN 2000+5
#define INF 1000000
using namespace std;
int u[MAXN],v[MAXN],w[MAXN],n,m,d[1005],first[1005],next[MAXN];
void read_graph()
{
    scanf("%d%d",&n,&m);
    for(int i=0; i<n; i++)
        first[i]=-1;
    for(int e=0; e<m; e++)
    {
        scanf("%d%d%d",&u[e],&v[e],&w[e]);
        next[e]=first[u[e]];
        first[u[e]]=e;
    }
}
bool ok;
void spfa()
{
    queue<int>q;
    ok=false;
    int vis[1005];
    memset(vis,0,sizeof(vis));
    bool inq[1005];
    d[0]=0;
    for(int i=1;i<n;i++)
        d[i]=INF;
    memset(inq,0,sizeof(inq));
    q.push(0);
    while(!q.empty())
    {
        int x=q.front();q.pop();
        inq[x]=false;
        for(int e=first[x];e!=-1;e=next[e])
        {
            if(d[v[e]]>d[x]+w[e])
            {
                d[v[e]]=d[x]+w[e];
                if(!inq[v[e]])
                {
                    inq[v[e]]=true;
                    vis[v[e]]++;
                    if(vis[v[e]]>n)
                    {
                        ok=true;
                        return ;
                    }
                    q.push(v[e]);
                }
            }
        }
    }
}
int main()
{
   // freopen("in.txt","r",stdin);
    int cas;
    scanf("%d",&cas);
    while(cas--)
    {
        read_graph();
        spfa();
        if(ok)
            puts("possible");
        else puts("not possible");
    }
    return 0;
}


### UVa818 切断圆链问题解决方案 对于UVa818切断圆链的问题,目标是在最少切割次数的情况下将给定长度的闭合链条分割成指定数量的小段。该问题可以通过贪心算法来有效求解。 #### 贪婪策略分析 为了最小化切割次数,在每次操作时应尽可能多地利用已有的切口位置。具体来说,当需要制作n个链接时,只需要做(n-1)次切割即可完成任务[^1]。 #### 实现方法概述 程序接收一系列整数作为输入数据,表示所需制造的不同尺寸片段数目;接着计算并输出达到这些要求所需的最低切割次数。这里给出Python版本的具体实现: ```python def min_cuts_needed(links): """Calculate minimum cuts needed to produce given link counts.""" # Remove duplicates and sort descendingly unique_links = sorted(set(links), reverse=True) total_cuts, current_length = 0, 0 while unique_links: next_cut = unique_links.pop(0) if not unique_links or (unique_links[0]*2 >= next_cut): total_cuts += 1 current_length = next_cut elif sum(unique_links)*2 < next_cut: break else: temp_sum = 0 index_to_remove = None for i, val in enumerate(unique_links): temp_sum += val if temp_sum*2 >= next_cut: index_to_remove = i break del unique_links[:index_to_remove+1] total_cuts += 1 current_length = next_cut return max(total_cuts - 1, 0) if __name__ == "__main__": import sys input_data = list(map(int, sys.stdin.readline().strip().split())) result = min_cuts_needed(input_data[:-1]) print(result) ``` 此代码实现了上述贪婪策略,并通过标准输入读取测试案例中的链接需求列表。注意最后会减去一次因为初始状态下的虚拟“零”切片[^1]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值