浴谷1645-序列(差分约束系统)

题目链接

题目描述

有一个整数序列,它的每个数各不相同,我们不知道它的长度是多少(即整数个数),但我们知道在某些区间中间至少有多少个整数,用区间(Li,Ri,Ci)来描述,表示这个整数序列中至少有Ci个数来自区间[Li,Ri],给出若干个这样的区间,问这个整数序列的长度最少能为多少?

输入输出格式

输入格式:

 

第一行一个整数N,表示区间个数;

接下来N行,每行三个整数(Li,Ri,Ci),描述一个区间。

【数据规模】

N<=1000,0<=Li<=Ri<=1000,1<=Ci<=Ri-Li+1

 

输出格式:

 

仅一个数,表示该整数序列的最小长度。

 

输入输出样例

输入样例#1: 复制

4
4 5 1
6 10 3
7 10 3
5 6 1

输出样例#1: 复制

4

 

 

以前看过这个算法,不过没做过题,今天算是做到入门题吧。

差分约束系统最难的就是建模,如何根据已知的不等式构造出联通图。

 

因为题目要求的是最小值,所以我们要在构造的图中求最长路。

假设现在有区间【L , R】,且最少有x个数。我们可以得到不等式 R-L+1>=x,即我们要构造addedge(L,R+1,x)这样的一条边.

当然,根据已知的条件构造出的图可能是不连通的,所以我们还需要找题目中隐藏的不等式条件来使得建模后的图一定联通,并且可以求出最长路。

隐藏的不等式?

当左右区间相等时,我们可以得到这样的一个不等式  0<=R-L+1<=1,所以又可以构造两条边 addedge(L,R+1,0),addedge(R+1,L,-1)。

这样我们就保证了图的连通性。

 

一开始做此题的时候,想法是将不等式左边的1移到右边构造addedge(L,R,x-1)的边,可是这样是错误的。

想了许久,只能找到这样的反例,在隐藏的不等式里,如果这样加边,仍然不能保证图的可连通性。

不知这样想是否正确,如果有路过的大佬,还敬请指点一二,证明一番。

 

 

/*#include
#include
#include
#include
#include
#include
#include
#include
#include
#define max(a,b)   (a>b?a:b)
#define min(a,b)   (apa;
const int MAXL(1000);
const int INF(0x3f3f3f3f);
const int mod(1e9+7);
int dir[4][2]= {{-1,0},{1,0},{0,1},{0,-1}};
struct node
{
    int ed,w;
} nod;
vectorv[MAXL+50];
int vis[MAXL+50];
int dis[MAXL+50];
void addedge(int x,int y,int w)
{
    v[x].push_back(node{y,w});
}
int SPFA(int u,int ma)
{
    queueq;
    memset(vis,0);
    memset(dis,-INF);
    vis[u]=1;
    dis[u]=0;
    q.push(u);
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        vis[t]=0;
        for(int i=0; i
#include
#include
#include
#include
#include
#include
#include
#include
#define max(a,b)   (a>b?a:b)
#define min(a,b)   (apa;
const int MAXL(1e6);
const int INF(0x3f3f3f3f);
const int mod(1e9+7);
int dir[4][2]= {{-1,0},{1,0},{0,1},{0,-1}};
struct node
{
    int to,next,w;

}edge[MAXL+50];
int head[MAXL+50];
int vis[MAXL+50];
int dis[MAXL+50];
int cnt=0;
void addedge(int x,int y,int w)
{
    edge[cnt].to=y;
    edge[cnt].next=head[x];
    edge[cnt].w=w;
    head[x]=cnt++;
}
int SPFA(int u,int ma)
{
    queueq;
    memset(vis,0);
    memset(dis,-INF);
    vis[u]=1;
    dis[u]=0;
    q.push(u);
    while(!q.empty())
    {
        int t=q.front();
        q.pop();
        vis[t]=0;
        for(int i=head[t]; ~i; i=edge[i].next)
        {
            int x=edge[i].to;
            if(dis[x]

 

你可能感兴趣的:(图论)