HDU 3572 Task Schedule[Dinic多路增廣優化]
阿新 • • 發佈:2018-11-10
題意:有n個任務,每個任務三個引數,P,S,E,分別代表需要工作的時間,起始時間,終止時間. 工作的P天可以不連續.每天可以同時進行M個任務.問,是否有合理的安排計劃.
思路:
- 每個任務對於區間[S,E]連一條邊,代表這些路徑都可以嘗試
- 對於每個任務,從源點S流入P的流量
- 對於每一天,都流向一個匯點T,容量為M
這樣建好圖後,跑一遍最大流,若證明一定有合理的計劃
Accepted 3572 452MS 3380K 2120B G++
按理說Dinic的複雜度是. 題目中 n->1000 , m->5e5 . 但Dinic對於某些特殊的圖,跑的特快
對於邊容量都是1的情況,複雜度為
#include<bits/stdc++.h> typedef long long ll; using namespace std; const int N=1e3+3,M=6e5; const int inf=1e9+9; int cnt; int ver[M<<1],edge[M<<1],Next[M<<1],head[N<<1]; void add(int u,int v,int w){ ver[++cnt]=v;edge[cnt]=w;Next[cnt]=head[u];head[u]=cnt; } void init(){ memset(head,-1,sizeof head); cnt=1; } int s,t; int dis[N]; bool bfs(){ memset(dis,0,sizeof dis); dis[s]=1; queue<int> q; q.push(s); while(!q.empty()){ int x=q.front();q.pop(); for(int i=head[x];i!=-1;i=Next[i]){ if(edge[i]>0 && !dis[ver[i]]){ dis[ver[i]]=dis[x]+1; q.push(ver[i]); if(ver[i]==t) return true; } } } return false; } int Dinic(int x,int flow){ if(x==t || flow==0) return flow; int res=0; for(int i=head[x];i!=-1;i=Next[i]){ if( flow-res>0&&dis[ver[i]]==dis[x]+1&& edge[i]){ ///flow-res>0 少一次遞迴,優化 int k=Dinic(ver[i],min(flow-res,edge[i])); if(!k) dis[ver[i]]=0; edge[i]-=k; edge[i^1]+=k; res+=k; } } return res; } int ks; bool vis[600]; int main(void){ int m,n; int T; scanf("%d",&T); while(T--){ memset(vis,false,sizeof vis); int mn=999,mx=0; scanf("%d%d",&n,&m); init(); s=0,t=500+n+1; ll tot=0; for(int i=1;i<=n;i++){ int p,st,ed; scanf("%d%d%d",&p,&st,&ed); tot+=p; add(s,500+i,p); add(500+i,s,0); for(int j=st;j<=ed;j++){ add(500+i,j,1); add(j,500+i,0); vis[j]=true; } } for(int i=1;i<=500;i++){ if(!vis[i]) continue; add(i,500+n+1,m); add(500+n+1,i,0); } ll maxflow=0; int flow; while(bfs()){ while(flow=Dinic(s,inf)) maxflow+=flow; } // cout << maxflow <<endl; printf("Case %d: ",++ks); if(maxflow==tot) printf("Yes\n\n"); else printf("No\n\n"); } return 0; }