1. 程式人生 > >網路流:HDU 2883

網路流:HDU 2883

HDU 2883

Sample Input
2 10
1 10 6 3
2 10 4 2

2 10
1 10 5 3
2 10 4 2

Sample Output
Yes
No

題意:一個n和m,表示有n個客戶,m個烤架。下面有n行每行四個輸入,si,ni,ti,ei,客戶si時刻到達,ei時刻離開,他需要ni串烤串,每串烤串需要ti的時間來烤。最後問你能否找出一個烤的順序,可以在客戶要求的時間內完成所有客戶的需求。可以輸出Yes,不行則輸出No。

偷看這個大佬的
解題思路:偷偷偷,大概講一下,對輸入的時間點進行排序去重,然後用相鄰的兩個時間構成的區間和客戶建點,我們可以轉化一下這個任務的要求,本來是說烤肉的串數,我們可以轉化成需要花費的工作量,那麼一個區間內最多能花費的工作量就是時間m,一個客戶要求的工作量就是ni

ti,以這個為流量,我們對於每個客戶,遍歷我們整理好的時間區間,如果客戶的時間區間包含這個區間,那麼就可以在這個時間區間裡來做客戶要求的任務,既建一條流量為niti或者inf的邊。源點和客戶建邊流量為niti,時間區間向匯點建邊流量為時間*m。然後跑最大流看看是不是滿流就可以了。

完整程式碼:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn=405; const int inf=0x3f3f3f3f; struct Edge{ int u,v,c; int next; }edge[maxn*maxn]; int n,m; int edn;//邊數 int head[maxn*maxn],dis[maxn*maxn]; int sp,tp;//原點,匯點 void addedge(int u,int v,int c) { edge[edn].u=u; edge[edn].v=v; edge[edn].c=c; edge[edn].next=head[u]; head[u]=edn++
; edge[edn].u=v; edge[edn].v=u; edge[edn].c=0; edge[edn].next=head[v]; head[v]=edn++; } int bfs() { queue <int> q; memset(dis,-1,sizeof(dis)); dis[sp]=0; q.push(sp); while(!q.empty()) { int cur=q.front(); q.pop(); for(int i=head[cur];i!=-1;i=edge[i].next) { int u=edge[i].v; if(dis[u]==-1 && edge[i].c>0) { dis[u]=dis[cur]+1; q.push(u); } } } return dis[tp] != -1; } int dfs(int a,int b) { int r=0; if(a==tp)return b; for(int i=head[a];i!=-1 && r<b;i=edge[i].next) { int u=edge[i].v; if(edge[i].c>0 && dis[u]==dis[a]+1) { int x=min(edge[i].c,b-r); x=dfs(u,x); r+=x; edge[i].c-=x; edge[i^1].c+=x; } } if(!r)dis[a]=-2; return r; } int dinic(int sp,int tp) { int total=0,t; while(bfs()) { while(t=dfs(sp,inf)) total+=t; } return total; } int s[maxn]; int e[maxn]; int ti[maxn]; int ni[maxn]; int a[maxn]; int cnt; int main() { int i,u,v,c; while(scanf("%d%d",&n,&m)!=EOF) { edn=0,cnt=0;//初始化 memset(head,-1,sizeof(head)); int sum=0; for(int i=1;i<=n;i++) { scanf("%d%d%d%d",&s[i],&ni[i],&e[i],&ti[i]); a[++cnt]=s[i]; a[++cnt]=e[i]; sum+=(ni[i]*ti[i]); } sort(a+1,a+1+cnt); cnt=unique(a+1,a+1+cnt)-a-1; sp=0,tp=n+cnt+1; for(int i=1;i<=n;i++) { addedge(sp,i,ni[i]*ti[i]); } for(int i=1;i<cnt;i++) { addedge(n+i,tp,(a[i+1]-a[i])*m); for(int j=1;j<=n;j++) { if(e[j]>=a[i+1]&&s[j]<=a[i]) { addedge(j,n+i,(a[i+1]-a[i])*m); } } } int ans=dinic(sp,tp); if(ans==sum) printf("Yes\n"); else printf("No\n"); } return 0; }