大致题意:
需要选一些整数点,给出m个约束条件,每个条件表述为,(s,t)表示在从s到t的区间内至少有2个点被选择。求最少选择多少个点。
大致思路:
和poj1201基本相同,在此不再赘述。这道题的点是从0开始取的,要小心数组越界。
详细代码:
#include<iostream> #include<cmath> #include<cstdio> #include<cstring> using namespace std; const int nMax=105000; const int mMax=10000500; const int inf=1<<28; struct{ int v, next; int w; }edge[mMax]; int n, k, head[nMax]; int dis[nMax]; int stack[nMax],m,sum[nMax]; bool vis[nMax]; void addedge(int a,int b,int w){ edge[k].w = w; edge[k].v=b; edge[k].next=head[a]; head[a]=k;k++; } bool spfa(int s){ int i, top = 0; memset(vis,0,sizeof(vis)); for(i=0;i<=n;i++)dis[i]=-inf; dis[s]=0; stack[++top]=s; vis[s]=true; while(top){ int u=stack[top--]; for(i=head[u];i!=0;i=edge[i].next){ int v=edge[i].v; if(dis[v]<dis[u]+edge[i].w){ dis[v]=dis[u]+edge[i].w; if(!vis[v]){ vis[v]=true; stack[++top] = v; if(++sum[v]>n)return 0; } } } vis[u]=false; } return 1; } int main(){ int m,s,t,c,i,j; while(scanf("%d",&m)!=EOF){ k=1; n=-1; memset(sum,0,sizeof(sum)); memset(head,0,sizeof(head)); while(m--){ scanf("%d%d",&s,&t); s++,t++; n=max(n,t); addedge(s-1,t,2); } s=n+2; for(i=0;i<=n;i++){ addedge(i+1,i,-1); addedge(i,i+1,0); } for(i=0;i<=n;i++){ addedge(s,i,0); } spfa(s); cout<<dis[n]<<endl; } return 0; }