bzoj3389:[Usaco2004 Dec]Cleaning Shifts安排值班
思路:可以贪心,也可以最短路。
贪心写法:因为在保证合法的前提下,我们选择的区间一定要右端点尽量靠后才行,于是我们每次就选择一个合法的并且右端点最靠后的区间就好了(如果没有合法的输出-1即可)。时间复杂度O(nlogn)(排序是nlogn的,贪心是O(n)的)。
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define maxn 25005 int n,t,ans; int last[1000005]; struct node{ int l,r; bool operator <(const node &a)const{return l<a.l||(l==a.l&&r<a.r);} }a[maxn]; inline int read(){ int x=0;char ch=getchar(); for (;ch<'0'||ch>'9';ch=getchar()); for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; return x; } int main(){ n=read(),t=read(); for (int i=1;i<=n;i++) a[i].l=read(),a[i].r=read(); sort(a+1,a+n+1);int cnt=0; for (int i=1;i<=n;i++) if (a[i].l!=a[i+1].l) a[++cnt]=a[i]; n=cnt;int now=0; for (int i=1;i<=n;i++){ int x=0;bool flag=0; while (a[i].l<=now+1&&i<=n) x=max(x,a[i].r),i++,flag=1; if (!flag){ans=-1;break;} if (x>now) now=x,ans++; i--; } if (now!=t) ans=-1; printf("%d\n",ans); return 0; }
最短路写法:区间[l,r]表示可以从l-1走到r,那么我们就把l-1连一条权值为1的边到r即可,然后又因为区间可以有交集,所以还需要将i向i-1连一条权值为0的边,然后以0为起点跑最短路即可(以0为起点是因为是l-1连向r)。时间复杂度O(TlogT)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> using namespace std; #define maxn 1000005 #define inf 1e9 int n,t,tot; int now[maxn],pre[maxn*2],son[maxn*2],val[maxn*2],dis[maxn]; bool vis[maxn]; inline int read(){ int x=0;char ch=getchar(); for (;ch<'0'||ch>'9';ch=getchar()); for (;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; return x; } void add(int a,int b,int c){ son[++tot]=b; pre[tot]=now[a]; now[a]=tot; val[tot]=c; } void link(int a,int b,int c){ add(a,b,c); } struct node{ int id,val; node(){} node(int a,int b){id=a,val=b;} bool operator <(const node &a)const{return val>a.val;} }; priority_queue<node> heap; void dijkstra(int x){ memset(dis,127,sizeof(dis)),dis[x]=0; heap.push(node(x,0)); while (!heap.empty()){ node x=heap.top();heap.pop();int id=x.id,v=x.val; if (vis[id]) continue;vis[id]=1; for (int p=now[id];p;p=pre[p]) if (dis[son[p]]>v+val[p]) heap.push(node(son[p],dis[son[p]]=v+val[p])); } } int main(){ n=read(),t=read(); for (int i=1,a,b;i<=n;i++) a=read(),b=read(),link(a-1,b,1); for (int i=1;i<=t;i++) link(i,i-1,0); dijkstra(0); if (dis[t]>1e9) puts("-1");else printf("%d\n",dis[t]); return 0; }