zoj 1508 差分约束 Bellman-Ford
You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn.
Write a program that:
> reads the number of intervals, their endpoints 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
The first line of the input contains an integer n (1 <= n <= 50 000) - the
number of intervals. The following n lines describe the intervals. The i+1-th
line of the input contains three integers ai, bi and ci separated by single
spaces and such that 0 <= ai <= bi <= 50 000 and 1 <= ci <= bi
- ai + 1.
Process to the end of file.
Output
The output contains exactly one integer equal to the minimal size of set Z sharing
at least ci elements with interval [ai, bi], for each i = 1, 2, ..., n.
Sample Input
5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1
Sample Output
6
Source: Southwestern Europe 2002
参考了《数与图的完美结合--浅析差分约束系统》,by 张威:http://pan.baidu.com/share/link?shareid=508660&uk=2720516383&fid=743287535
对属于区间[ai, bi]的任意元素,按属于于不属于题述序列关系,可定义如下映射:
t=0,表某元素不在序列中;1,表在序列中。
则可令Si= 从ai-1到bi,求和(t),即Si表该区间[ai,bi]中在序列的元素个数。至此,不难构造不等式(组):
S(bi)-S(ai-1)>=ci;另外由任意S(i)与S(i-1)的关系也可得:
0<=S(i)-S(i-1)<=1; 转化为:
S(ai-1) - S(bi) <= -ci
S(i-1) - S(i) <= 0
S(i) - S(i-1) <= 1
于是就可以直接建图用bellmanford算法了,但答案是多少呢?这里我不很清楚,可能是这样建图产生负权边,然后求相对值吧。论文给出的是d[最大节点标号]-d[最小节点标号,即0].
AC代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cmath> 6 #include<vector> 7 #include<cstdlib> 8 #include<algorithm> 9 #include<queue> 10 11 using namespace std; 12 13 #define LL long long 14 #define ULL unsigned long long 15 #define UINT unsigned int 16 #define MAX_INT 0x7fffffff 17 #define MAX_LL 0x7fffffffffffffff 18 #define MAX(X,Y) ((X) > (Y) ? (X) : (Y)) 19 #define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) 20 21 #define MAXN 66666 22 #define MAXM 200000 23 #define INF 100000 24 25 struct edge{ 26 int u,v,nxt,w; 27 }e[MAXM]; 28 int cc,h[MAXN]; 29 int inq[MAXN],d[MAXN]; 30 int ans; 31 32 inline void add(int u, int v, int w){ 33 e[cc]=(edge){u,v,h[u],w}; 34 h[u]=cc++; 35 } 36 37 queue<int> q; 38 int bford(int s, int n){ 39 int u,i,w,v; 40 while(!q.empty()) q.pop(); q.push(s); 41 // memset(cnt, 0, sizeof(cnt)); cnt[s]=1; 42 memset(inq, 0, sizeof(inq)); inq[s]=1; 43 for(i=0; i<n; i++) d[i]=INF; d[s]=0; 44 while(!q.empty()){ 45 u=q.front(); q.pop(); inq[u]=0; 46 for(i=h[u]; i!=-1; i=e[i].nxt){ 47 v=e[i].v; 48 w=e[i].w; 49 if(d[v]>d[u]+w){ 50 d[v]=d[u]+w; 51 if(!inq[v]){ 52 // if(++cnt[v]>n) return 1; 53 q.push(v); 54 inq[v]=1; 55 } 56 } 57 } 58 } 59 ans=d[s-1]-d[0]; // 结果不是d[s-1]么?。。。 60 return 0; 61 } 62 63 #define POINT(x) ((x) < 0 ? 0 : (x) ) 64 65 int main(){ 66 // freopen("C:\\Users\\Administrator\\Desktop\\in.txt","r",stdin); 67 int n; 68 while(scanf(" %d",&n)==1){ 69 int a,b,c; 70 int i,ub=0; 71 cc=0; 72 memset(h, -1, sizeof(h)); 73 for(i=0; i<n; i++){ 74 scanf(" %d %d %d",&a,&b,&c); 75 add(b, POINT(a-1), -c); // S(bi) - S(ai-1) <= C(i) --如果a-1<0,则用0代替a-1,仍满足,此时0表示ai-1项不存在 76 ub=MAX(ub, b); // 记录最大点编号 77 } 78 ub++; 79 for(i=1; i<ub; i++){ 80 add(i, i-1, 0); // S(i-1) - S(i) <= 0 81 add(i-1, i, 1); // S(i) - S(i-1) <= 1 82 } 83 for(i=0; i<ub; i++) add(ub, i, 0); // S(ub+1) - i <= 0 --虚拟源点,编号ub+1 84 85 bford(ub, ub+2); // 共有ub+2个点 86 printf("%d\n", ans); 87 } 88 return 0; 89 }