• pku1201 Intervals


    这题目,我差点彻底崩溃了,郁闷死了,一开始一直TLE,原来只有一个测试数据,这叫我情何以堪……

    后来,还发现了一个错误,就是构图时候,最大节点跟最小节点还是要标记一下比较好,我本来是默认0是最小节点的,可是在后面添加新边的时候又添加了一个0节点,唉

    就是Sbi+1-Sai>=Ci,这样来添加边计较保险

    用数组模拟队列来实现SPFA的时候,数组要绝对的足够大,我就这样RE了无数次,最后Q[maxn*10]才过的,但此时内存已经很大了

    不过也可以直接用STL里面的queue来做,方便很多,内存也不算很大

    还有用栈实现的,这个就很省内存啦

    为什么用栈写有时候会很快呢? 首先它很节省空间,因为最多有v-1个节点同时在栈内。其次,它在栈底的点并不容易出栈,所以等到这些节点出栈的时候,它已经被松弛的差不多了。说白了还是一个概率型优化方法。
    spfa是一个不稳定的算法,用队列实现有点像广搜。当然大家可以用深搜实现一下。因为即使用栈写,那也是广度优先搜索的思路。因为它是‘一层一层’执行,而深搜是‘一个一个’执行。所以用深搜的思路写,效率可想而知了。

    下面是俩种方式的SPFA:

    数组模拟队列实现
    #include <iostream>
    #include
    <algorithm>
    #include
    <queue>
    using namespace std;
    #define MAXN 50005
    #define INF 0x6fffffff
    struct Edge{
    int v;
    int w;
    int next;
    }edge[
    150000];
    int head[MAXN];
    bool vis[MAXN];
    int dis[MAXN];
    int stack[MAXN*10];
    int n;
    int ind;
    int Max,Min;

    void add_edge(int u,int v,int w)
    {
    edge[ind].v
    =v;
    edge[ind].w
    =w;
    edge[ind].next
    =head[u];
    head[u]
    =ind++;
    }
    void Init(int e)
    {
    for(int i=0;i<=e;i++)
    {
    vis[i]
    =false;
    dis[i]
    =-INF;
    }
    }
    void spfa()
    {
    Init(Max);
    dis[Min]
    =0;
    int begin,end;
    begin
    = end = 0;
    stack[end
    ++] = Min;
    vis[Min]
    = true;
    while(begin<end)
    {
    int t = stack[begin++];
    for(int j = head[t];j!=-1;j = edge[j].next)
    {
    if(dis[edge[j].v]<edge[j].w+dis[t])
    {
    dis[edge[j].v]
    = edge[j].w+dis[t];
    if(!vis[edge[j].v])
    {
    vis[edge[j].v]
    = true;
    stack[end
    ++] = edge[j].v;
    }
    }
    }
    vis[t]
    = false;
    }
    }

    int main() {
    scanf(
    "%d",&n);
    memset(head,
    -1,sizeof(head));
    int u,v,w;
    ind
    =0;
    Max
    =0;Min=INF;
    for(int i=1;i<=n;i++)
    {
    scanf(
    "%d%d%d",&u,&v,&w);
    if(v+1>Max)Max=v+1;
    if(u<Min)Min=u;
    add_edge(u,v
    +1,w);
    }
    for(int i=Min;i<Max;i++)
    {
    add_edge(i,i
    +1,0);
    add_edge(i
    +1,i,-1);
    }
    spfa();
    // for(int i=Min;i<=Max;i++)printf("%d\n",dis[i]);
    printf("%d\n",dis[Max]);
    //printf("%d %d\n",Max,Min);
    return 0;
    }
    用数组模拟栈实现
    #include<stdio.h>
    #include
    <stdlib.h>
    #define INF 0xfffffff
    #define NN 50004
    #define MM 150004
    int edNum, maxn;
    int mark[NN];
    int root[NN];
    int dis[NN];
    int stack[NN];
    struct node{
    int e, v,next;
    }edge[MM];

    void Init(){
    int i;
    for (i = 0; i < NN; i++){
    mark[i]
    = 0;
    root[i]
    = -1;
    dis[i]
    = INF;
    }
    }

    void add(int a, int b, int c){
    edge[edNum].e
    = b;
    edge[edNum].v
    = c;
    edge[edNum].next
    = root[a];
    root[a]
    = edNum++;
    }

    void Spfa()
    {
    int i, cur, nxt, tmp, top = 0;
    for (i = 0; i <= maxn; i++){
    if (root[i] != -1){
    stack[
    ++top] = i;
    mark[i]
    = 1;
    }
    }
    // 这里需要注意,要将终点置零,求的就是别的点到终点maxn的距离
    dis[maxn] = 0;
    while (top){
    cur
    = stack[top--];
    mark[cur]
    = 0;
    tmp
    = root[cur];
    while (tmp != -1){
    nxt
    = edge[tmp].e;
    if (dis[nxt] > dis[cur] + edge[tmp].v){
    dis[nxt]
    = dis[cur] + edge[tmp].v;
    if (!mark[nxt]){
    mark[nxt]
    = 1;
    stack[
    ++top] = nxt;
    }
    }
    tmp
    =edge[tmp].next;
    }
    }
    }
    int main()
    {
    int n, i, a, b, c;
    scanf(
    "%d", &n);
    maxn
    = 0;
    edNum
    = 0;
    Init();
    for (i = 1; i <= n; i++){
    scanf(
    "%d%d%d", &a, &b, &c);
    add(b
    + 1, a, -c);
    if (b + 1 > maxn){
    maxn
    = b + 1;
    }
    }
    for (i = 0; i <= maxn; i++){
    add(i
    + 1, i, 0);
    add(i, i
    + 1, 1);
    }
    Spfa();
    //输出的时候也要注意,是起点到终点的距离的负值
    printf("%d\n", -dis[0]);
    // system("pause");
    return 0;
    }




  • 相关阅读:
    Python之socket_tcp
    Python之多进程&异步并行
    Qt forever关键字
    Qt程序在XP系统上不能正常运行
    Qt多线程的使用
    QScrollArea
    QtoolButton
    QComboBox
    Qt播放音频文件
    Qt5.9.1编译oracle驱动
  • 原文地址:https://www.cnblogs.com/nanke/p/2137082.html
Copyright © 2020-2023  润新知