POJ 1716 Integer Intervals【差分约束+SPFA】
2016-06-03 17:08
447 查看
Integer Intervals
Description
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.
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
Source
CEOI 1997
同POJ 1201
题目大意:给出n个约束条件,从每个区间【a,b】都至少取出两个元素,使得最终组成的集合个数最少。
思路:差分约束转最短路。
差分约束转最短路问题首要思想就是要构成这样的一个式子就能构成一条有向边:
tb-ta<=k
那么我们的目标就是在已知条件中,转化问题为这个形式,我们也就能够转化问题到最短路上。
1、首先,我们需要对ti进行赋予含义:ti表示【0,i-1】中选取元素的个数,那么:tb+1-ta>=2,也就有:
ta-tb+1<=-2;
2、只有这个条件的话,图是不连通的,我们还有这样一个等式就能够使得图连通:
0<=ti-ti-1<=1
3、确定起点终点,起点就是所给约束条件中最小编号的节点,终点就是所给约束条件中最大编号的节点,然后我们进行一次SPFA,然后输出dis【终点】即可,对于负值的输出情况,我们转为正值即可。
AC代码’:
#include<stdio.h>
#include<string.h>
#include<queue>
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
int head[500000];
int vis[500000];
int dis[500000];
int n;
struct EdgeNode
{
int to;
int w;
int next;
}e[500000];
int cont;
void add(int from,int to,int w)
{
e[cont].to=to;
e[cont].w=w;
e[cont].next=head[from];
head[from]=cont++;
}
int abs(int w)
{
if(w<0)return -w;
else return w;
}
void SPFA(int start)
{
memset(vis,0,sizeof(vis));
for(int i=0;i<=n;i++)dis[i]=INF;
queue<int >s;
s.push(start);
vis[start]=1;
dis[start]=0;
while(!s.empty())
{
int u=s.front();
//printf("u:%d\n",u);
s.pop();vis[u]=0;
for(int j=head[u];j!=-1;j=e[j].next)
{
int v=e[j].to;
int w=e[j].w;
// printf("%d %d\n",v,w);
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(vis[v]==0)
{
s.push(v);
vis[v]=1;
}
}
}
}
printf("%d\n",abs(dis
));
//printf("%d\n",sum);
}
int main()
{
int m;
int s;
while(~scanf("%d",&m))
{
cont=0;
n=0;
memset(vis,0,sizeof(vis));
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++)
{
int x,y,w;
scanf("%d%d",&x,&y);
s=min(s,x);
n=max(n,y+1);
add(x,y+1,-2);
}
for(int i=0;i<n;i++)
{
add(i+1,i,1);
add(i,i+1,0);
}
SPFA(s);
}
}
/*
7
4 9 5
8 9 1
5 6 1
3 9 5
7 9 1
3 4 1
2 5 3
*/
Time Limit: 1000MS | | Memory Limit: 10000K |
Total Submissions: 13671 | | Accepted: 5824 |
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.
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
Source
CEOI 1997
同POJ 1201
题目大意:给出n个约束条件,从每个区间【a,b】都至少取出两个元素,使得最终组成的集合个数最少。
思路:差分约束转最短路。
差分约束转最短路问题首要思想就是要构成这样的一个式子就能构成一条有向边:
tb-ta<=k
那么我们的目标就是在已知条件中,转化问题为这个形式,我们也就能够转化问题到最短路上。
1、首先,我们需要对ti进行赋予含义:ti表示【0,i-1】中选取元素的个数,那么:tb+1-ta>=2,也就有:
ta-tb+1<=-2;
2、只有这个条件的话,图是不连通的,我们还有这样一个等式就能够使得图连通:
0<=ti-ti-1<=1
3、确定起点终点,起点就是所给约束条件中最小编号的节点,终点就是所给约束条件中最大编号的节点,然后我们进行一次SPFA,然后输出dis【终点】即可,对于负值的输出情况,我们转为正值即可。
AC代码’:
#include<stdio.h>
#include<string.h>
#include<queue>
#include<iostream>
using namespace std;
#define INF 0x3f3f3f3f
int head[500000];
int vis[500000];
int dis[500000];
int n;
struct EdgeNode
{
int to;
int w;
int next;
}e[500000];
int cont;
void add(int from,int to,int w)
{
e[cont].to=to;
e[cont].w=w;
e[cont].next=head[from];
head[from]=cont++;
}
int abs(int w)
{
if(w<0)return -w;
else return w;
}
void SPFA(int start)
{
memset(vis,0,sizeof(vis));
for(int i=0;i<=n;i++)dis[i]=INF;
queue<int >s;
s.push(start);
vis[start]=1;
dis[start]=0;
while(!s.empty())
{
int u=s.front();
//printf("u:%d\n",u);
s.pop();vis[u]=0;
for(int j=head[u];j!=-1;j=e[j].next)
{
int v=e[j].to;
int w=e[j].w;
// printf("%d %d\n",v,w);
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(vis[v]==0)
{
s.push(v);
vis[v]=1;
}
}
}
}
printf("%d\n",abs(dis
));
//printf("%d\n",sum);
}
int main()
{
int m;
int s;
while(~scanf("%d",&m))
{
cont=0;
n=0;
memset(vis,0,sizeof(vis));
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++)
{
int x,y,w;
scanf("%d%d",&x,&y);
s=min(s,x);
n=max(n,y+1);
add(x,y+1,-2);
}
for(int i=0;i<n;i++)
{
add(i+1,i,1);
add(i,i+1,0);
}
SPFA(s);
}
}
/*
7
4 9 5
8 9 1
5 6 1
3 9 5
7 9 1
3 4 1
2 5 3
*/
相关文章推荐
- Android重启app功能实现
- MySQL中获取当前时间与时间戳
- 墨菲定律、二八法则、马太效应、手表定理、“不值得”定律、彼得原理、零和游戏、华盛顿合作规律、酒与污水定律、水桶定律、蘑菇管理原理、钱的问题、奥卡姆剃刀等13条是左右人生的金科玉律
- memory库函数的实现
- 分享一个我的JavaScript版GridView多功能表格
- 优惠购书
- nginx 的限制连接模块limit_zone与limit_req_zone
- 【java】字符串查找
- 浅谈C++中的mutable和volatile关键字
- 从datagridview中导出数据到excel
- FFT原理及实现
- Leetcode之combination-sum-ii
- LeetCode OJ: 9. Palindrome Number (C++)
- git ! [rejected] master -> master (fetch first)
- C# JsonAdpater json 处理类
- 返回函数
- 使用C语言扩展Python
- java的static块执行时机
- 字符串的二进制存储读取
- deviceToken 唯一标识?