您的位置:首页 > 其它

Poj 1201 Intervals

2013-08-24 20:00 357 查看
题目链接:http://poj.org/problem?id=1201

差分约束系统。

我们用s[i]代表从[0,i]所含有的元素和

在本题中,如果[a,b]中有c个元素,那么:

s[b]-s[a-1]>=c,我们可以推得:s[a-1] - s[b] <= -c

同时,由于每一个值上最多只能含有一个元素,那么:

s[i] - s[i-1]<=1

s[i] - s[i-1]>=0 推得:s[i-1] - s[i] <=0

这样:我们有了三个约束不等式:

s[a-1] - s[b] <= -c

s[i] - s[i-1]<=1

s[i-1] - s[i] <=0

于是:

假设题目中所有查询的所在区间范围是:[start,end]的话,那么:

我们只要求出:s[end] -s[start-1] >= M就可以了。

其中M就是我们要的最小值。

我们可以整理成我们容易求解的形式:即:s[start-1] - start[end] <= -M

就是求从end这一点,到start-1这一点的最短路径。

然后求出的最短路径求相反数就是M了。

注意题目要求a可以为0,所有都++避免下标为负。Bellmanford会超时,spfa是首选。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stack>
#include <queue>
#include <algorithm>
#include <iostream>

using namespace std;

#define Maxn 50005
#define Maxm 200005
#define INF 0x3f3f3f3f

int first[Maxn];
int next[Maxm];
int total;
struct Edge
{
int a,b;
int w;
}edge[Maxm];

int dist[Maxn];
int vis[Maxn];
void init()
{
total = 0;
memset(first,-1,sizeof(first));
}
void addEdge(int a,int b,int w)
{
edge[total].a = a,edge[total].b = b,edge[total].w = w;
next[total] = first[a];
first[a] = total++;
}
/*
bool bellmanFord(int start,int pointNum,int m)
{
memset(dist,0x3f,sizeof(dist));
dist[start] = 0;
for(int i=0;i<pointNum-1;i++)
{
for(int j=0;j<m;j++)
{
int a = edge[j].a;
int b = edge[j].b;
int w = edge[j].w;
if(dist[a] + w < dist[b]) dist[b] = dist[a] + w;
}
}
for(int i=0;i<m;i++)
{
int a = edge[i].a;
int b = edge[i].b;
int w = edge[i].w;
if(dist[a] + w < dist[b])
{
return false;
}
}
return true;
}*/
int cnt[Maxn];
bool spfa(int s,int n)
{
memset(dist,0x3f,sizeof(dist));
memset(vis,0,sizeof(vis));
memset(cnt,0,sizeof(cnt));
dist[s] = 0;
queue<int> q;
q.push(s);
vis[s] = 1;
while(!q.empty())
{
int temp = q.front();
q.pop();
vis[temp] = 0;
for(int i=first[temp];i!=-1;i=next[i])
{
int a = edge[i].a;
int b = edge[i].b;
int w = edge[i].w;
if(dist[a] + w < dist[b])
{
dist[b] = dist[a] + w;
if(!vis[b])
{
vis[b] = 1;
cnt[b]++;
if(cnt[b] > n) return false;
q.push(b);
}
}
}
}
//判负环
return true;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
int n;
int a,b,c;
int start,end;
while(scanf(" %d",&n)!=EOF)
{
init();
start = INF,end = -INF;
for(int i=1;i<=n;i++)
{
scanf(" %d %d %d",&a,&b,&c);
a++,b++;
start = min(start,a);
end = max(end,b);
//b-a>=c -> a-b<=-c
addEdge(b,a-1,-c);
}
for(int i=start;i<=end;i++)
{
//Si - Si-1 <= 1
addEdge(i-1,i,1);
//Si-1 - Si <= 0
addEdge(i,i-1,0);
}
//if(!bellmanFord(end,end-start+2,total)) continue;
if(!spfa(end,end-start+2)) continue;
int ans = -dist[start-1];
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: