差分约束详解,详解!!!hdoj 1384
来源:互联网 发布:淘宝家具店铺排行榜 编辑:程序博客网 时间:2024/06/03 20:24
今天看了下最短路径相关的查分约束,感觉自己理解了一点点,
想把今天学的记录下,也希望小伙伴指出不足之处!!嘻嘻嘻!
查分约束:
就是给出一些形如x-y<=b不等式的约束,问你是否满足有解的问题!
但是就是在这里比较难以转化!
(建图问题)
给出道题目进行讲解: http://acm.hdu.edu.cn/showproblem.php?pid=1384
题意:有n个区间,给出每个区间的左端点和右端点以及在该区间至少有多少个数在集合Z里面,
现在让你求出集合Z里面最少元素个数
思路: MAX,MIN分别代表区间的右端点和左端点,dist[i]存储从源点到某点i的最短路
下面的是自己总结的两种方法:(注意<,>方向)
(1)对于差分不等式,b-a <= c ,建一条 b 到 a 的权值为 -c 的边,求的是最短路,得到的是最大值
首先定义一个数组dist[i],存放的i是:从源点到某点i的最短路,b-a >= c转化a-b<=-c,题目中还有一个隐藏条件
和前面的有建图时的权值有差别,主要是源点建立不同,注意!
想把今天学的记录下,也希望小伙伴指出不足之处!!嘻嘻嘻!
查分约束:
就是给出一些形如x-y<=b不等式的约束,问你是否满足有解的问题!
但是就是在这里比较难以转化!
(建图问题)
给出道题目进行讲解: http://acm.hdu.edu.cn/showproblem.php?pid=1384
题意:有n个区间,给出每个区间的左端点和右端点以及在该区间至少有多少个数在集合Z里面,
现在让你求出集合Z里面最少元素个数
思路: MAX,MIN分别代表区间的右端点和左端点,dist[i]存储从源点到某点i的最短路
下面的是自己总结的两种方法:(注意<,>方向)
(1)对于差分不等式,b-a <= c ,建一条 b 到 a 的权值为 -c 的边,求的是最短路,得到的是最大值
首先定义一个数组dist[i],存放的i是:从源点到某点i的最短路,b-a >= c转化a-b<=-c,题目中还有一个隐藏条件
0<=dist[i+1]-dist[i]<=1;转化为dist[i+1]-dist[i]<=1, dist[i]-dist[i+1]<=0;再用邻接表进行建图!
b-a>=c --> a-b<=-c类型!!
代码 :
#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;#include<queue>#define INF 0xffffff#define N 50000+100int MAX=-1,top=0,T;int MIN=INF;int head[N],visit[N],dist[N];struct Edge{ int from; int to; int weight; int next; }edge[N*(N-1)/2];void addEdge(int u,int v,int w){ edge[top].from =u; edge[top].to =v; edge[top].weight =w; edge[top].next =head[u]; head[u]=top++;}void init(){ top=0; memset(head,-1,sizeof(head)); }void Getp(){ int a,b,c,i,j; for(i=1;i<=T;i++) { scanf("%d%d%d",&a,&b,&c); MAX=max(MAX,b); MIN=min(MIN,a); addEdge(b,a-1,-c);//反向建图 权值为-c ,a-b<=-c } for(i=MIN;i<=MAX;i++)//隐藏条件! { addEdge(i,i-1,0);//dist[i]-dist[i+1]<=0 addEdge(i-1,i,1);// dist[i+1]-dist[i]<=1 }}void spfa(){ int i,j; queue <int > Q; Q.push(MAX); for(i=MIN-1;i<=MAX;i++) dist[i]=i==MAX?0:INF; memset(visit,0,sizeof(visit)); visit[MAX]=1; while(!Q.empty()) { int q=Q.front(); Q.pop(); visit[q]=0; for(i=head[q];i!=-1;i=edge[i].next ) { int u=edge[i].to ; if(dist[u]>dist[q]+edge[i].weight ) { dist[u]=dist[q]+edge[i].weight ; if(!visit[u]) { visit[u]=1; Q.push(u); } } } } printf("%d\n",-dist[MIN-1]);//从源点《最大》到MIN-1之间 ,即到MIN的最短路径 }int main(){ while(scanf("%d",&T)!=EOF) { init(); Getp(); spfa(); } return 0;}(2)<对于不等式 a - b>= c ,建一条 b 到 a 的权值为 c 的边,求的是最长路,得到的是最小值>
和前面的有建图时的权值有差别,主要是源点建立不同,注意!
b-a<=c ---> a-b>=-c ,如果方向合适b-a>=c时,无需变化!
代码:
#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>using namespace std;#include<queue>#define INF 0xffffff#define N 50000+100int MAX=-1,top=0,T;int MIN=INF;int head[N],visit[N],dist[N];struct Edge{int from;int to;int weight;int next; }edge[N*(N-1)/2];void addEdge(int u,int v,int w){edge[top].from =u;edge[top].to =v;edge[top].weight =w;edge[top].next =head[u];head[u]=top++;}void init(){top=0;memset(head,-1,sizeof(head));}void Getp(){ int a,b,c,i,j;for(i=1;i<=T;i++){scanf("%d%d%d",&a,&b,&c);b++;MAX=max(MAX,b);MIN=min(MIN,a);addEdge(a,b,c);}for(i=MIN;i<MAX;i++)//隐藏条件! {addEdge(i+1,i,-1);addEdge(i,i+1,0);}}void spfa(){int i,j;queue <int > Q;Q.push(MIN);for(i=MIN;i<=MAX;i++)dist[i]=i==MIN?0:-INF;memset(visit,0,sizeof(visit));visit[MIN]=1;while(!Q.empty()){int q=Q.front();Q.pop();visit[q]=0;for(i=head[q];i!=-1;i=edge[i].next ){int u=edge[i].to ;if(dist[u]<dist[q]+edge[i].weight ){dist[u]=dist[q]+edge[i].weight ;if(!visit[u]){visit[u]=1;Q.push(u);}}}}printf("%d\n",dist[MAX]);}int main(){while(scanf("%d",&T)!=EOF){init();Getp();spfa();}return 0;}
0 1
- 差分约束详解,详解!!!hdoj 1384
- 差分约束详解
- 差分约束详解
- 差分约束详解
- 差分约束 详解
- 差分约束系统详解
- 差分约束系统详解
- 差分约束系统详解
- 差分约束系统详解
- 差分约束系统详解
- 差分约束系统详解
- 差分约束系统详解
- 差分约束系统详解
- 差分约束系统详解
- 差分约束系统详解
- 差分约束系统详解
- 差分约束系统详解
- 差分约束系统详解
- 第二章 一切都是对象
- spark 自定义排序详解
- [ruby]Rails中使用bootstrap
- Android基础之Activity系列 - Activity间的数据传递
- 入职(一)
- 差分约束详解,详解!!!hdoj 1384
- android NFC开发
- C循环语句
- mysql 建表时类型长度的意思
- 最近一段时间总结(一)
- HDOJ【5575】【单调栈】【可并堆】
- Python扩展库psutil用法精要
- 【Codeforces Round 331 (Div 2)A】【水题】Wilbur and Swimming Pool 给出矩形1~4个顶点让你还原矩形
- 【tmp】引论