【POJ 1716】Integer Intervals(差分約束系統)
阿新 • • 發佈:2018-03-14
入門題 put AD edge ota 全部 lib 最小 最短
Write a program that: finds the minimal number of elements in a set containing at least two different integers from each interval.
Output the minimal number of elements in a set containing at least two different integers from each interval.
id=1716">【POJ 1716】Integer Intervals(差分約束系統)
Time Limit: 1000MS | ? | Memory Limit: 10000K |
Total Submissions: 13425 | ? | Accepted: 5703 |
Description
An integer interval [a,b], a < b, is a set of all consecutive integers beginning with a and ending with b.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
Sample Input
4 3 6 2 4 0 2 4 7
Sample Output
4
Source
field=source&key=CEOI+1997">CEOI 1997
實訓回來後的一血~~
差分約束系統,走前看了點,沒搞透,做完這題略微有點明確了。
這題是差分約束系統入門題,關於差分約束系統。百度各種大牛博客講的都非常具體。簡單說就是通過不等關系建立約束系統圖,然後跑最短路(大於關系則跑最長路)
回到此題,題目要求找出一個最小集合S,滿足對於n個範圍[ai,bi],S中存在兩個及兩個以上不同的點在範圍內
令Zi表示滿足條件的情況下。0~i點至少有多少點在集合內
則Zb-Za >= 2
僅僅有這一個條件構造出來的圖可能不是全然連通的,所以須要找一些“隱含條件”
不難發現 對於相鄰的點 0 <= Zi-Z(i-1) <= 1 保證關系符同樣 轉化為
Zi-Z(i-1) >= 0
Z(i-1)-Zi >= -1
用這三個關系,就可以構造差分約束系統,然後SPFA或者Bellman跑一趟最長路(滿足全部條件)
代碼例如以下:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <queue> using namespace std; const int INF = 0x3f3f3f3f; const int msz = 1e5; const int mod = 1e9+7; const double eps = 1e-8; struct Edge { int v,w,next; }; Edge eg[233333]; int head[50050]; bool vis[50050]; int dis[50050]; int tp,st,en; void Add(int u,int v,int w) { eg[tp].v = v; eg[tp].w = w; eg[tp].next = head[u]; head[u] = tp++; } int SPFA() { memset(vis,0,sizeof(vis)); memset(dis,-INF,sizeof(dis)); queue <int> q; dis[st] = 0; vis[st] = 1; int u,v,w; q.push(st); while(!q.empty()) { u = q.front(); q.pop(); vis[u] = 0; for(int i = head[u]; i != -1; i = eg[i].next) { v = eg[i].v; w = eg[i].w; if(dis[v] < dis[u]+w) { dis[v] = dis[u]+w; if(!vis[v]) { q.push(v); vis[v] = 1; } } } } return dis[en]; } int main(int argc,char **argv) { int n; int u,v; while(~scanf("%d",&n)) { tp = 0; memset(head,-1,sizeof(head)); en = 0,st = INF; while(n--) { scanf("%d%d",&u,&v); Add(u,v+1,2); //最小點做起點 最大點做終點 en = max(en,v+1); st = min(st,u); } for(int i = st; i < en; ++i) { Add(i,i+1,0); Add(i+1,i,-1); } printf("%d\n",SPFA()); } return 0; }
【POJ 1716】Integer Intervals(差分約束系統)