POJ 1201 Intervals(差分约束-spfa)
2016-03-15 11:03
429 查看
Description
构造一个集合,这个集合内的数字需要满足所给的n个条件,每个条件都是指在[a,b]中至少有c个数在集合内,问这个集合最少包含多少个点
Input
第一行一整数n表示条件数,之后n行每行三个整数ai,bi,ci表示一个条件
(1<=n<=50000,1<=ai<=bi<=50000,1<=ci<=bi-ai+1)
Output
输出这个集合最少包含多少个点
Sample Input
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
Sample Output
6
Solution
令T[i]表示在[0,i-1]内最少需要选的数,那么每个条件都可以转化为T[a]-T[b+1]<=-c,这是就考虑到差分约束了,但是条件还需要完善,因为每个数字最多选一次,最少不选,所以有0<=T[i]-T[i-1]<=1,即T[+1]-T[i]<=1,T[i]-T[i+1]<=0,之后用spfa求最短路即为答案,注意此题极限情况取条件中所有数字一定满足条件所以不需要构造超级源点也不需要判负环
Code
构造一个集合,这个集合内的数字需要满足所给的n个条件,每个条件都是指在[a,b]中至少有c个数在集合内,问这个集合最少包含多少个点
Input
第一行一整数n表示条件数,之后n行每行三个整数ai,bi,ci表示一个条件
(1<=n<=50000,1<=ai<=bi<=50000,1<=ci<=bi-ai+1)
Output
输出这个集合最少包含多少个点
Sample Input
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
Sample Output
6
Solution
令T[i]表示在[0,i-1]内最少需要选的数,那么每个条件都可以转化为T[a]-T[b+1]<=-c,这是就考虑到差分约束了,但是条件还需要完善,因为每个数字最多选一次,最少不选,所以有0<=T[i]-T[i-1]<=1,即T[+1]-T[i]<=1,T[i]-T[i+1]<=0,之后用spfa求最短路即为答案,注意此题极限情况取条件中所有数字一定满足条件所以不需要构造超级源点也不需要判负环
Code
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #include<queue> using namespace std; #define INF 0x3f3f3f3f #define maxn 55555 #define maxm 222222 struct edge { int to,next; int cost; }g[maxm]; int head[maxm],tol; int dis[maxn];//所有点到起点的最短距离 int cnt[maxn];//统计每个点的入队次数,若入队次数大于顶点数说明有负环 void init()//初始化 { memset(head,-1,sizeof(head)); tol=0; } void add(int u,int v,int c)//单向边,从u到v,权值为c { g[tol].cost=c; g[tol].to=v; g[tol].next=head[u]; head[u]=tol++; } int spfa(int s,int n)//单源最短路,s是起点,n为点数 { bool vis[maxn]; memset(vis,false,sizeof(vis)); memset(cnt,0,sizeof(cnt)); queue<int>que; for(int i=0;i<maxn;i++) dis[i]=INF; cnt[s]++; dis[s]=0; vis[s]=true; que.push(s); while(!que.empty()) { int u=que.front(); que.pop(); vis[u]=false; for(int i=head[u];i!=-1;i=g[i].next) { int v=g[i].to; int c=g[i].cost; if(dis[v]>dis[u]+c) { dis[v]=dis[u]+c; if(!vis[v]) { vis[v]=true; que.push(v); cnt[v]++; if(cnt[v]>n)return 1;//存在负环 } } } } return 0;//不存在负环 } int main() { int n,a,b,c,m; while(~scanf("%d",&n)) { init(); m=0; for(int i=1;i<=n;i++) { scanf("%d%d%d",&a,&b,&c); add(a,b+1,-c); m=max(m,b); } m++; for(int i=0;i<m;i++)add(i+1,i,1),add(i,i+1,0); spfa(0,m+1); printf("%d\n",-dis[m]); } return 0; }
相关文章推荐
- [数论] [codevs 1702 素数判定2] 费马定理+验证法
- opencv动态目标跟踪学习总结
- json数据解析
- 地理信息
- java开发--JavaScript
- PHP闭包函数传参及使用外部变量的方法
- vmm强制删除主机
- Jquery常用功能笔记
- 数据库编码问题,搜索中文内容获取不到内容
- mac下yii框架的搭建
- linux上LCD应用程序编写 柏贵林
- $("#form1 :input" )与$("#form1input")的区别
- GBD调试简介
- android中jar包的导出和导入
- 自定义view(二)
- [Canvas绘图] 第34节 藏图阁(14) AlphaGo与李世石的围棋大战之第四局
- VMware安装Centos
- 将 Entity Framework、LINQ 和 Model-First 用于 Oracle 数据库
- dns服务器报错解决
- Guava库