POJ 1201 & HDU1384 & ZOJ 1508 Intervals(差分约束+spfa 求最长路径)
来源:互联网 发布:视频矩阵和硬盘录像机 编辑:程序博客网 时间:2024/05/22 05:02
题目链接:
POJ:http://poj.org/problem?id=1201
HDU:http://acm.hdu.edu.cn/showproblem.php?pid=1384
ZOJ:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=508
Description
Write a program that:
reads the number of intervals, their end points and integers c1, ..., cn from the standard input,
computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i=1,2,...,n,
writes the answer to the standard output.
Input
Output
Sample Input
53 7 38 10 36 8 11 3 110 11 1
Sample Output
6
Source
题意:(转)
[ai, bi]区间内和点集Z至少有ci个共同元素,那也就是说如果我用Si表示区间[0,i]区间内至少有多少个元素的话,那么Sbi - Sai >= ci,这样我们就构造出来了一系列边,权值为ci,但是这远远不够,因为有很多点依然没有相连接起来(也就是从起点可能根本就还没有到终点的路线),此时,我们再看看Si的定义,也不难写出0<=Si - Si-1<=1的限制条件,虽然看上去是没有什么意义的条件,但是如果你也把它构造出一系列的边的话,这样从起点到终点的最短路也就顺理成章的出现了。
我们将上面的限制条件写为同意的形式:
Sbi - Sai >= ci
Si - Si-1 >= 0
Si-1 - Si >= -1
这样一来就构造出了三种权值的边,而最短路自然也就没问题了。
但要注意的是,由于查分约束系统里常常会有负权边,所以为了避免负权回路,往往用Bellman-Ford或是SPFA求解(存在负权回路则最短路不存在)。
PS:
因为求的是[ai,bi]区间,所以我们添加边的时候需要(u-1, v, w)!
把距离dis初始化为负无穷, if(dis[v] < dis[u] + w)即可!
POJ 和ZOJ用队列和栈都能过,但是HDU用栈会超时,只能用队列!
代码如下:(栈)
#include <cstdio>#include <cstring>#include <stack>#include <iostream>#include <algorithm>using namespace std;#define INF 0x3f3f3f3f#define N 50017#define M 50017int n, m, k;int Edgehead[N], dis[N];struct Edge{ int v,w,next;} Edge[3*M];bool vis[N];//int cont[N];int minn, maxx;int MIN(int a, int b){ if(a < b) return a; return b;}int MAX(int a, int b){ if(a > b) return a; return b;}void Addedge(int u, int v, int w){ Edge[k].next = Edgehead[u]; Edge[k].w = w; Edge[k].v = v; Edgehead[u] = k++;}int SPFA( int start)//stack{ int sta[N]; int top = 0; //memset(cont,0,sizeof(cont); for(int i = 1 ; i <= n ; i++ ) dis[i] = -INF; dis[start] = 0; //++cont[start]; memset(vis,false,sizeof(vis)); sta[++top] = start; vis[start] = true; while(top) { int u = sta[top--]; vis[u] = false; for(int i = Edgehead[u]; i != -1; i = Edge[i].next)//注意 { int v = Edge[i].v; int w = Edge[i].w; if(dis[v] < dis[u] + w) { dis[v] = dis[u]+w; if( !vis[v] )//防止出现环 { sta[++top] = v; vis[v] = true; } //if(++cont[v] > n)//有负环 //return -1; } } } return dis[maxx];}int main(){ int u, v, w; while(~scanf("%d",&n))//n为目的地 { k = 1; memset(Edgehead,-1,sizeof(Edgehead)); minn = INF; maxx = -1; for(int i = 1 ; i <= n ; i++ ) { scanf("%d%d%d",&u,&v,&w); Addedge(u-1,v,w); maxx = MAX(v,maxx); minn = MIN(u-1,minn); } for(int i = minn; i <= maxx; i++)//新边,保证图的连通性还必须添加每相邻两个整数点i,i+1的边 { Addedge(i,i+1,0); Addedge(i+1,i,-1); } int ans = SPFA(minn);//从点minn开始寻找最短路 printf("%d\n",ans); } return 0;}
HDU队列:
#include <cstdio>#include <cstring>#include <stack>#include <iostream>#include <algorithm>#include <queue>using namespace std;#define INF 0x3f3f3f3f#define N 50017#define M 50017int n, m, k;int Edgehead[N], dis[N];struct Edge{ int v,w,next;} Edge[3*M];bool vis[N];//int cont[N];int minn, maxx;int MIN(int a, int b){ if(a < b) return a; return b;}int MAX(int a, int b){ if(a > b) return a; return b;}void Addedge(int u, int v, int w){ Edge[k].next = Edgehead[u]; Edge[k].w = w; Edge[k].v = v; Edgehead[u] = k++;}int SPFA( int start)//stack{ queue<int>q; //int sta[N]; //memset(cont,0,sizeof(cont); int top = 0; for(int i = minn ; i <= maxx ; i++ ) dis[i] = -INF; dis[start] = 0; //++cont[start]; memset(vis,false,sizeof(vis)); //sta[++top] = start; q.push(start); vis[start] = true; while(!q.empty()) { //int u = sta[top--]; int u = q.front(); q.pop(); vis[u] = false; for(int i = Edgehead[u]; i != -1; i = Edge[i].next)//注意 { int v = Edge[i].v; int w = Edge[i].w; if(dis[v] < dis[u] + w) { dis[v] = dis[u]+w; if( !vis[v] )//防止出现环 { //sta[++top] = v; q.push(v); vis[v] = true; } // if(++cont[v] > n)//有负环 // return -1; } } } return dis[maxx];}int main(){ int u, v, w; while(~scanf("%d",&n))//n为目的地 { k = 1; memset(Edgehead,-1,sizeof(Edgehead)); minn = INF; maxx = -1; for(int i = 1 ; i <= n ; i++ ) { scanf("%d%d%d",&u,&v,&w); Addedge(u-1,v,w); maxx = MAX(v,maxx); minn = MIN(u-1,minn); } for(int i = minn; i <= maxx; i++)//新边,保证图的连通性还必须添加每相邻两个整数点i,i+1的边 { Addedge(i,i+1,0); Addedge(i+1,i,-1); } int ans = SPFA(minn);//从点minn开始寻找最短路 printf("%d\n",ans); } return 0;}
- POJ 1201 & HDU1384 & ZOJ 1508 Intervals(差分约束+spfa 求最长路径)
- POJ 1201 & HDU1384 & ZOJ 1508 Intervals 差分约束
- POJ1201 HDU1384 Intervals【SPFA】【差分约束】
- poj 1201 Intervals(差分约束求最长路)
- HDU1384 Intervals (差分约束系统)
- poj1201&&hdu1384 Intervals(差分约束)
- POJ 1201 Intervals 差分约束+spfa
- poj 1201 Intervals 差分约束 + spfa
- poj 1201 Intervals 差分约束+spfa
- [差分约束] HDU1384 Intervals
- POJ 1201 Intervals(差分约束-Spfa)
- 【POJ 1201】Intervals(差分约束+SPFA)
- poj 1201/ZOJ 1508 Intervals 差分约束
- poj 1201 Intervals(差分约束,最长路)
- ZOJ 1508 Intervals (差分约束系统+spfa)
- POJ1201/ZOJ1508/HDU1384 Intervals(spfa解差分约束问题)
- POJ1201(Hdu1384) Intervals差分约束系统
- hdu1384 poj1202 Intervals --- 差分约束
- 三种照片保存形式 :JPEG、TIFF、RAW
- POJ 3096 && HDU 2736 Surprising Strings(水~)
- Ubuntu QT5.5.0 安装
- Linux内核RCU(Read Copy Update)锁简析
- android 定位
- POJ 1201 & HDU1384 & ZOJ 1508 Intervals(差分约束+spfa 求最长路径)
- 判断两个时间是不是同一天
- E-JSON数据传输标准
- Android:Volley源码解析
- 黑马程序员——Java String类 and 正则表达式(第七篇)
- POJ 3100 && HDU 2740 Root of the Problem(水~)
- nltk在python中的安装,以及nltk的data库
- HBase使用常见异常
- HDU5280 Senior's Array(简单DP)