POJ 1201
http://poj.org/problem?id=1201
题目大意:
有一个序列,题目用n个整数组合 [ai,bi,ci]来描述它,[ai,bi,ci]表示在该序列中处于[ai,bi]这个区间的整数至少有ci个。如果存在这样的序列,请求出满足题目要求的最短的序列长度是多少。
思路:
设s[i]为从1~i的整数个数。
这样对于区间[ a , b]显然有 S[b+1] - S[a] >=c[i] (为什么是b+1?因为闭区间b也要选上呀)
然后还有
0<= S[B+1]-S[B] <=1 (整数的话最多比前一个大一,好吧,我大二- -|||我不二啊!!)
变形得:
S[B+1]-S[B] >=0
S[B]-S[B+1]>=-1
然后图就可以建立出来啦~~~~
#include <cstdio> #include<cstring> #include<queue> #include <algorithm> using namespace std; const int MAXN=50000+10; const int MAXM=50000*3+10; int head[MAXN],len,L,R,n; struct edge { int to,next; int val; }e[MAXM]; void add(int from,int to,int val) { e[len].to=to; e[len].val=val; e[len].next=head[from]; head[from]=len++; } bool vis[MAXN]; int dis[MAXN]; int spfa() { queue<int> q; for(int i=L;i<=R;i++) { vis[i]=1; dis[i]=0; q.push(i); } while(!q.empty()) { int cur=q.front(); q.pop(); vis[cur]=false; for(int i=head[cur];i!=-1;i=e[i].next) { int id=e[i].to; if(e[i].val+dis[cur] > dis[id]) { dis[id]=e[i].val+dis[cur] ; if(!vis[id]) { vis[id]=true; q.push(id); } } } } return dis[R]; } int main () { while(~scanf("%d",&n)) { memset(head,-1,sizeof(head)); R=len=0;L=0x7fffff; for(int i=1;i<=n;i++) { int from,to,val; scanf("%d%d%d",&from,&to,&val); R=max(to+1,R); L=min(L,from); add(from,to+1,val); } for(int i=L;i<=R;i++) { add(i,i+1,0); add(i+1,i,-1); } printf("%d\n",spfa()); } return 0; }
POJ 1716
http://poj.org/problem?id=1716
思路和上面的一样,只不过下标多1而已。
#include<cstdio> #include<cstring> #include<queue> using namespace std; const int MAXN=10000+10; const int MAXM=300000+1000; const int INF=-100000000; struct edge { int to; int val; int next; }e[MAXM]; int head[MAXN],dis[MAXN],len,n,m; void add(int from,int to,int val) { e[len].to=to; e[len].val=val; e[len].next=head[from]; head[from]=len++; } void spfa(int start) { bool vis[MAXN]={0}; deque<int> q; q.push_back(start); vis[start]=1; dis[start]=0; while(!q.empty()) { int cur=q.front(); q.pop_front(); vis[cur]=false; for(int i=head[cur];i!=-1;i=e[i].next) { int id=e[i].to; if(dis[id] < dis[cur] + e[i].val) { dis[id]=dis[cur] + e[i].val; if(!vis[id]) { vis[id]=true; if(!q.empty() && dis[id] > dis[q.front()]) q.push_back(id); else q.push_front(id); } } } } } int main() { while(~scanf("%d",&m)) { memset(head,-1,sizeof(head)); len=0; int s=10000; n=0; for(int i=0;i<m;i++) { int from,to; scanf("%d%d",&from,&to); add(from,to+1,2); if(s > from) s=from; if(n < to) n=to; } for(int i=0;i<=n;i++) //start到n就WA,不明觉厉 { add(i,i+1,0); add(i+1,i,-1); // add(0,i+1,0); //加了也能过,不过比较慢 dis[i+1]=INF; } spfa(0); printf("%d\n",dis[n+1]); } return 0; }