Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 25784 | Accepted: 9870 |
Description
Write a program that:
reads the number of intervals, their end points and integers c1, ..., cn from the standard input,
computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i=1,2,...,n,
writes the answer to the standard output.
Input
Output
Sample Input
5 3 7 3 8 10 3 6 8 1 1 3 1 10 11 1
Sample Output
6
這個題就是讓你找出一個總的序列s包括如:
3 4 5 6 7 的序列中s中至少有三個
8-10中s至少有3個
6-8中s至少有1個
1-3中s至少有1個
10 11中至少有1個
問你s最少有多少個能滿足上述的情況。
這題我們就用差分約束的方法,可以令題目更簡單
這裏我們用d數組來存(意義就是如:d[6]代表0-5中s最少包含幾個)
那麼條件就會滿足
0<=d[i+1]-d[i]<=1;
d[v+1]-d[u]>=dist;
我們求得是滿足所有的條件那麼就要找“最大路徑”也就是所有的條件都要“<=”
我們將上面的公式變形就會得到:
d[i+1]-d[i]<=1;
d[i]-d[i+1]<=0;
d[u]-d[v+1]<=-dist;
然後我們就可以用SPFA算法求得了。
代碼如下:
#include <cstring>
#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 50010;
const int INF = 0x3f3f3f3f;
struct node
{
int dist, to, next;
}E[3*N];
int head[N], d[N], n, tot;
bool vis[N];
void AddEdge(int u, int v, int dist)
{
E[tot].to = v;
E[tot].dist = dist;
E[tot].next = head[u];
head[u] = tot++;
}
void SPFA(int Min, int Max)
{
int i;
for ( i = Min;i <= Max; i++ )
{
d[i] = INF;
vis[i] = 0;
}
queue<int> q;
q.push(Max);
d[Max] = 0;
vis[Max] = 1;
while ( !q.empty() )
{
int u = q.front();
q.pop();
vis[u] = false;
for ( i = head[u]; i != -1; i = E[i].next)
{
int v = E[i].to;
if (d[v] > d[u] + E[i].dist)
{
d[v] = d[u] + E[i].dist;
if (!vis[v])
{
vis[v] = true;
q.push(v);
}
}
}
}
}
void solve()
{
memset( head, -1, sizeof(head) );
tot = 0;
int Min = INF, Max = -INF;
int u, v, i, h;
for ( i = 0;i < n; i++ )
{
scanf ( "%d %d %d", &u, &v, &h );
Min = min(Min, u);
Max = max(Max, v+1);
AddEdge(v+1, u, -h);
}
for ( i = 0;i < Max; i++ )
{
AddEdge(i, i+1, 1);
AddEdge(i+1, i, 0);
}
SPFA(Min, Max);
printf ( "%d\n", d[Max] - d[Min] );
}
int main()
{
while ( ~scanf ( "%d", &n ) )
{
solve();
}
return 0;
}
代碼菜鳥,如有錯誤,請多包涵!!!
如有幫助記得支持我一下,謝謝!!!