POJ1716
An integer interval [a,b], a < b, is a set of all consecutive integers beginning with a and ending with b.
Write a program that: finds the minimal number of elements in a set containing at least two different integers from each interval.
一个整数区间[A,B]是一个以a为开头,b为结尾的连续整数集合。写一个程序带有以下功能:找到满足在所有已知区间内都至少包含这个已知区间两个元素的这样一个区间的最小元素数。
Input
The first line of the input contains the number of intervals n, 1 <= n <= 10000. Each of the following n lines contains two integers a, b separated by a single space, 0 <= a < b <= 10000. They are the beginning and the end of an interval.
Output
Output the minimal number of elements in a set containing at least two different integers from each interval.
Sample Input
4
3 6
2 4
0 2
4 7
Sample Output
4
本题从差分约束的角度上来看,存在三个不等式:
- 假如说occurance[i]代表在[1,i]范围内所求区间与当前区间重叠元素数,那么必定存在occurance[b+1](此时包含区间右端点)-occurance[a]≥2(右端点减左端点的值,也就是在本区间内必须存在至少两个重叠元素)。
- 隐含条件:occurance[i]-occurance[i-1]≥0 和occurance[i]-occurance[i-1]≤1,也就是说在两个数之间(一个数的位置)不可能存在大于一个数的重叠情况和小于0的重叠情况。
整理可得occurance(以下简称o)
- o(i)-o(i-1)≥0
- o(i-1)-o(i)≥-1
- o(b+1)-o(a)≥2
对以上三种情况建边,因为是大于号,所以直接求最长路即可。
//#include<pch.h>
#include <iostream>
#include <cstdio>
//#include <bits/stdc++.h>
#include<queue>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf_s("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
#define debug cout<<"procedures above are available"<<endl;
using namespace std;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline ll lldcin()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
/**Maintain your determination.Nobody knows the magnificent landscape
at his destination before the arrival with stumble.**/
/**Last Remote**/
struct inter
{
ll left,right;
}intervals[20000];
struct edge
{
ll next,to,v;
}edges[230000];
ll heads[230000],cnt,dis[250000];
bool vis[250000];
void cons(ll from,ll to,ll v)
{
edges[cnt]=edge{heads[from],to,v};
heads[from]=cnt++;
}
bool cmp(inter a,inter b)
{
return a.right<b.right;
}
void spfa(ll s)
{
reset(dis,-0x3f3f3f3f);
reset(vis,0);
queue<ll>q;
q.push(s);
dis[s]=0;
vis[s]=1;
while(!q.empty())
{
ll current=q.front();
q.pop();
vis[current]=0;
for(int i=heads[current];i!=-1;i=edges[i].next)
{
ll t=edges[i].to;
if(dis[t]<dis[current]+edges[i].v)
{
dis[t]=dis[current]+edges[i].v;
if(!vis[t])
{
q.push(t);
vis[t]=1;
}
}
}
}
}
int DETERMINATION()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
ll n;
cin>>n;
ll mx=-1;
reset(heads,-1);
for(int i=1;i<=n;i++)
{
cin>>intervals[i].left>>intervals[i].right;
cons(intervals[i].left,intervals[i].right+1,2);//如不等式所表示
mx=max(mx,intervals[i].right);//找到最大值
}
for(int i=0;i<=mx+1;i++)
{
cons(i,i+1,0);//关于两个数间隔的不等式
cons(i+1,i,-1);
}
spfa(0);
cout<<dis[mx+1]<<endl;
return 0;
}
HDU3666 2010年区域赛哈尔滨赛区。
You have been given a matrix C N*M, each element E of C N*M is positive and no more than 1000, The problem is that if there exist N numbers a1, a2, … an and M numbers b1, b2, …, bm, which satisfies that each elements in row-i multiplied with ai and each elements in column-j divided by bj, after this operation every element in this matrix is between L and U, L indicates the lowerbound and U indicates the upperbound of these elements.
已经给定一个N*M的矩阵C,矩阵里每个元素E都是正数并且不大于1000。问题是如果存在N个整数a...和M个整数b...,满足条件:第i行的元素乘ai,第j列的元素除以bj后,这些元素的范围都是在L和U范围内的,L代表下界,U代表上界。
Input
There are several test cases. You should process to the end of file.
Each case includes two parts, in part 1, there are four integers in one line, N,M,L,U, indicating the matrix has N rows and M columns, L is the lowerbound and U is the upperbound (1<=N、M<=400,1<=L<=U<=10000). In part 2, there are N lines, each line includes M integers, and they are the elements of the matrix.
多组数据,请处理到EOF。
Output
If there is a solution print "YES", else print "NO".
Sample Input
3 3 1 6
2 3 4
8 2 6
5 2 9
Sample Output
YES
如果已知它是个差分约束,那么很明显这里就存在两个不等式
- (xij*ai)/bj>=L
- (xij*ai)/bj<=U
因为变量和常数间不存在明显的加减关系,只有乘除关系。所以对两边取对数,就可以得到有关式子,据此建边即可。
因为不存在明显的起点,单源点最短路算法不能解决多源点的情况,所以要人为添加一个起点,并使得它与所有点都连通。
为了避免冲突,这里b点的编号从n+1开始
//#include<pch.h>
#include <iostream>
#include <cstdio>
//#include <bits/stdc++.h>
#include<queue>
#include <map>
#include <algorithm>
#include <stack>
#include <iomanip>
#include <cstring>
#include <cmath>
#define DETERMINATION main
#define lldin(a) scanf_s("%lld", &a)
#define println(a) printf("%lld\n", a)
#define reset(a, b) memset(a, b, sizeof(a))
#define debug cout<<"procedures above are available"<<endl;
using namespace std;
const int INF = 0x3f3f3f3f;
const double PI = acos(-1);
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int mod = 1000000007;
const int tool_const = 19991126;
const int tool_const2 = 33;
inline ll lldcin()
{
ll tmp = 0, si = 1;
char c;
c = getchar();
while (c > '9' || c < '0')
{
if (c == '-')
si = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
{
tmp = tmp * 10 + c - '0';
c = getchar();
}
return si * tmp;
}
/**Maintain your determination.Nobody knows the magnificent landscape
at his destination before the arrival with stumble.**/
/**Last Remote**/
double a[500][500];
struct edge
{
int next, to;
double value;
}edges[700000];
int heads[2000], cnts[2000], cnt;
double dis[2000];
bool vis[2000];
void cons(int from, int to, double v)
{
edges[cnt] = edge{ heads[from],to,v };
heads[from] = cnt++;
}
bool spfa(int s, int total)
{
reset(vis, 0);
reset(dis, 0x3f3f3f);
reset(cnts, 0);
queue<ll>q;
q.push(s);
vis[s] = 1;
dis[s] = 0;
cnts[s]++;
while (!q.empty())
{
int current = q.front();
q.pop();
vis[current] = 0;
for (int i = heads[current]; i != -1; i = edges[i].next)
{
int t = edges[i].to;
if (dis[t] > edges[i].value + dis[current])
{
dis[t] = edges[i].value + dis[current];
if (!vis[t])
{
q.push(t);
vis[t] = true;
cnts[t]++;
if (cnts[t] > sqrt(total))
return false;
}
}
}
}
return true;
}
int DETERMINATION()
{
//ios::sync_with_stdio(false);
int n, m, l, u;
while (~scanf("%d %d %d %d", &n, &m, &l, &u))
{
cnt = 0;
reset(heads, -1);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
a[i][j] = lldcin();
for (int i = 1; i <= n; i++)
for (int j = 1; j <= m; j++)
{
cons(i, j + n, -log(ld(l) / a[i][j]));
cons(j + n, i, log(ld(u) / a[i][j]));//两个式子
}
for (int i = 1; i <= n + m; i++)
cons(0, i, 0);//超源点
bool res = spfa(0, m + n);
if (res)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}