POJ 1201 amp; HDU1384 amp; ZOJ 1508 Intervals(差分约束+spfa 求最长路径)
題目鏈接:
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
You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn.?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
The first line of the input contains an integer n (1 <= n <= 50000) -- 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 <= 50000 and 1 <= ci <= bi - ai+1.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 1Sample Output
6Source
Southwestern Europe 2002題意:(轉)
[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 50017 int 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 50017 int 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 amp; HDU1384 amp; ZOJ 1508 Intervals(差分约束+spfa 求最长路径)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 你想知道的关于JavaScript作用域
- 下一篇: pip: command not fou