题意:给你n个区间,然后你需要在区间中选取最少c个,这c个数存在于集合z中,问你集合z最少有多少个元素
思路:刚接触差分约束,感觉是一种套路,不过差分约束的模型的确不容易看出来(先感谢聚聚博客中对于差分约束的讲解,传送门),感觉讲的很清楚,对于最小值,找最长路,最大值最短路(可能这就是使用spfa的唯一道路,逃)
代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; inline LL read() { LL x=0,f=1;char ch=getchar(); while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } const int MAXN=50005; const int INF=-0x3f3f3f3f; int n,m,ans; int head[MAXN]; //int begin1,end1; int dis[MAXN],vis[MAXN]; struct node { int u,v,w; int next; }edge[MAXN<<2]; void init() { ans=0; memset(head,-1,sizeof(head)); } void add(int u,int v,int w) { edge[ans].u=u; edge[ans].v=v; edge[ans].w=w; edge[ans].next=head[u]; // next标记以u为起点的下一条边 head[u]=ans++; // head标记这个点是哪条边的起点,更新head } void SPFA(int begin1,int end1) { int i,j; queue<int>q; // for(int i=0;i<n;i++) dis[i]=INF; memset(dis,-0x3f,sizeof(dis)); memset(vis,0,sizeof(vis)); dis[begin1]=0,vis[begin1]=1; q.push(begin1); while(!q.empty()){ int u=q.front(); q.pop(); // printf("trst %d ",u); vis[u]=0; for(i=head[u];i!=-1;i=edge[i].next){ int top=edge[i].v; if(dis[top]<dis[u]+edge[i].w){ dis[top]=dis[u]+edge[i].w; if(!vis[top]){ vis[top]=1; q.push(top); } } } } // if(dis[end1]==INF) printf("-1 "); // else printf("%d ",dis[end1]); } int main() { while(~scanf("%d",&n)){ int s=999999,t=0; init(); for(int i=1;i<=n;i++){ int u=read(),v=read(),w=read(); add(u,v+1,w); s=min(s,u); t=max(t,v+1); } for(int i=s;i<t;i++)add(i,i+1,0),add(i+1,i,-1); SPFA(s,t); printf("%d ",dis[t]); } return 0; }