题解:P11614 [PA 2016] 任务排序 / Szeregowanie zadań
P11614 [PA 2016] 任务排序 / Szeregowanie zadań 题解
简单网络流,场切了。
solution
发现这道题严格弱于P2570 [ZJOI2010] 贪吃的老鼠,所以去掉那道题的二分即可 AC。
这里说一下更简单的建边方式:
首先将所有
然后设
源点向每个处理器连 INF 边,第
然后考虑如何处理处理器与任务之间的边,我们可以对第
可以发现,在题目的条件下,跑出的流一定可以对应一个分配处理器的合法方案,即满足题目中一个处理器同一时间只能处理一个任务,一个任务同一时间只能在一个处理器上被处理的限制。
于是跑完最大流后检查一下是否满流就可以了。
时间复杂度
code
代码中的变量定义与题目中略有不同。
// by MornStar
#include<bits/stdc++.h>
using namespace std;
using ll=long long;
const ll N=405,M=100505,INF=0x3f3f3f3f3f3f3f3f;
//N: max of node num
//M: max of edge num
//T: the type of max_flow
//INF: max of max_flow
//eps: is used to check the val is 0 or not
template<int N,int M,typename T,const T INF=0x3f3f3f3f,const T eps=0>
struct Dinic{
const int inf=0x3f3f3f3f;
int vnum,s,t;
struct edge{int to,pre;T w;}e[M<<1];
int head[N],now[N],cnt=1;
//use opt=1 to add undirected edge
void add_edge(int u,int v,T w=INF,int opt=0){
e[++cnt]={v,head[u],w};head[u]=cnt;
e[++cnt]={u,head[v],w*opt};head[v]=cnt;
}
int dis[N];
queue<int>q;
void set_information(int num,int _s,int _t){vnum=num,s=_s,t=_t;}
void set_dis(){for(int i=1;i<=vnum;i++) dis[i]=inf;}
void clear(){cnt=1,clear_head(),set_information(0,0,0);}
void clear_head(){for(int i=1;i<N;i++) head[i]=0;}
void clear_q(){while(!q.empty()) q.pop();}
bool bfs(){
clear_q(),set_dis();
dis[s]=0,now[s]=head[s];q.push(s);
while(!q.empty()){
int x=q.front();q.pop();
for(int i=head[x];i;i=e[i].pre){
edge &it=e[i];
if(it.w>eps&&dis[it.to]==inf){
dis[it.to]=dis[x]+1;
q.push(it.to),now[it.to]=head[it.to];
if(it.to==t) return 1;
}
}
}
return 0;
}
T dinic(int x,T flow){
if(x==t) return flow;
T ret=0;
for(int i=now[x];i&&(flow>eps);i=e[i].pre){
now[x]=i;
edge &it=e[i],&rev=e[i^1];
if(it.w>eps&&(dis[it.to]==dis[x]+1)){
T k=dinic(it.to,min(flow,it.w));
if(!k) dis[it.to]=inf;
it.w-=k,rev.w+=k,flow-=k,ret+=k;
}
}
return ret;
}
T max_flow(){
T ret=0;
while(bfs()) ret+=dinic(s,INF);
return ret;
}
T min_cut(){return max_flow();}
//upper and lower bound flow
bool check_full(){
for(int i=head[s];i;i=e[i].pre){
if(e[i].w>eps) return 0;
}
return 1;
}
void debug(){
for(int i=2;i<=cnt;i+=2) cerr<<e[i^1].to<<' '<<e[i].to<<" "<<e[i].w<<"\n";
}
};
Dinic<N,M,ll,INF>dc;
int n,m,l[N],r[N],t[N],b[N<<1],tb,num;
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>l[i]>>r[i]>>t[i],num+=t[i],b[++tb]=l[i],b[++tb]=r[i];
sort(b+1,b+tb+1);
tb=unique(b+1,b+tb+1)-b-1;
dc.set_information(N-1,N-2,N-1);
for(int i=1;i<=m;i++) dc.add_edge(dc.s,i,INF);
for(int i=1;i<=n;i++) dc.add_edge(m+i,dc.t,t[i]);
for(int i=1;i<tb;i++){
for(int j=1;j<=m;j++) dc.add_edge(j,n+m+i,b[i+1]-b[i]);
for(int j=1;j<=n;j++){
if(l[j]<=b[i]&&b[i+1]<=r[j]) dc.add_edge(n+m+i,m+j,b[i+1]-b[i]);
}
}
// dc.debug();
int ans=dc.max_flow();
if(ans==num) cout<<"TAK\n";
else cout<<"NIE\n";
}