JOJ2726:PLAN

2726 Plan
FJ has two same house for rant. Now he has n (1 ≤ n ≤ 1000) piece of order, the orders are 
given in the form: 
s t v
means that someone want to rant a house from the day s to t paying v yuan totally (including 
the day s and t, 0 ≤ s ≤ t ≤ 400, 0 ≤ v ≤ 100,0000). 
A hours can be only rant to one person, and FJ should either accept an order totally or reject it. 
Input
The first line of input file is a single integer T - The number of test cases. For each test case, 
the first line is a single integer n then there n lines, each line gives an order
Output
For each data set, print a single line containing an integer, the maximum total income for the 
data set
Sample Input
3
4
1 2 10
2 3 10
3 3 10
1 3 10
6
1 20 1000
3 25 10000
5 15 5000
22 300 5500
10 295 9000
7 7 6000
8
32 251 2261
123 281 1339
211 235 5641
162 217 72736
22 139 7851
194 198 9190
119 274 878
122 173 8640
Sample Output
30
25500
38595



唐牛春季网络流专场的一道题,今天做了一下。
发现最小费用流就能搞定,定义完数组发现如果以order为点肯定超时了,所以re看了一下题,发现t的范围很小,都是整数,所以果断改图,把每秒作为点就OK了。
建图方法:相邻两个点(t,t + 1)连线,流量是2,费用是0,对于每一个order,s + 1和t + 2连线(t + 2多加1是因为防止有起始点与它相同,出现流错误)流量为1,费用为-c,在这个图上做一边最小费用流就行了。
SPFA很犀利,不过极限数据还是跑不进0.00s.....
代码:
#include <cstdio>
#include <cstring>
#define min(a, b) (a > b ? b : a)
using  namespace std;

const  int maxn = 405;
const  int maxm = 3300;
const  int inf = 1 << 30;
int n;

struct Edge
{
     int v, next, c, w;
} edge[maxm];

int head[maxn], cnt;

void add_edge( int u,  int v,  int w,  int c)
{
    edge[cnt].v = v;
    edge[cnt].w = w;
    edge[cnt].c = c;
    edge[cnt].next = head[u];
    head[u] = cnt++;

    edge[cnt].v = u;
    edge[cnt].w = 0;
    edge[cnt].c = -c;
    edge[cnt].next = head[v];
    head[v] = cnt++;
}

int dis[maxn], pre[maxn];
int alpha[maxn];
int que[maxn], qhead, qrear;

int spfa( int s,  int e)
{
     for ( int i = 0; i < maxn; ++i)
        dis[i] = inf;
    memset(alpha, 0,  sizeof(alpha));
    dis[s] = 0;
    que[qhead = 0] = s;
    qrear = 1;
    alpha[s] = 1;
     while (qhead != qrear)
    {
         int k = que[qhead++];
        qhead %= maxn;
        alpha[k] = 0;
         for ( int q = head[k]; ~q; q = edge[q].next)
             if (edge[q].w)
                 if (dis[k] + edge[q].c < dis[edge[q].v])
                {
                    dis[edge[q].v] = dis[k] + edge[q].c;
                    pre[edge[q].v] = q;
                     if (!alpha[edge[q].v])
                    {
                        alpha[edge[q].v] =  true;
                         if (edge[q].c < 0)
                        {
                            qhead = (qhead - 1 + maxn) % maxn;
                            que[qhead] = edge[q].v;
                        }
                         else
                        {
                            que[qrear++] = edge[q].v;
                            qrear %= maxn;
                        }
                    }
                }
    }
     if (dis[e] == inf)  return -1;
     int k = inf;
     for ( int i = e; i != s; i = edge[pre[i] ^ 1].v)
       k = min(k, edge[pre[i]].w);
     return k;
}

int mcmf( int s,  int t)
{
     int ans = 0, k;
     while (~(k = spfa(s, t)))
    {
         for ( int i = t; i != s; i = edge[pre[i] ^ 1].v)
        {
            edge[pre[i]].w -= k;
            edge[pre[i] ^ 1].w += k;
        }
        ans += dis[t] * k;
    }
     return ans;
}

void init()
{
    cnt = 0;
    memset(head, -1,  sizeof(head));
}

int main()
{
     int T;
    scanf("%d", &T);
     while (T--)
    {
        init();
        scanf("%d", &n);
         for ( int i = 0; i < n; ++i)
        {
             int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            add_edge(a + 1, b + 2, 1, -c);
        }
         for ( int i = 0; i <= 401; ++i)
            add_edge(i, i + 1, 2, 0);
         int ans = mcmf(0, 402);
        printf("%d\n", -ans);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值