ZOJ3229 Shoot the Bullet(有源汇流量有上下界网络的最大流)
题目大概说在n天里给m个女孩拍照,每个女孩至少要拍Gi张照片,每一天最多拍Dk张相片且都有Ck个拍照目标,每一个目标拍照的张数要在[Lki, Rki]范围内,问最多能拍几张照片。
源点-天-女孩-汇点,这样子建容量网络。然后就是求这个有源汇流量有上下界容量网络的最大流:
- 首先计算其可行流,POJ2396
- 然后删除附加源、附加汇以及汇点到源点容量INF的边
- 最后从源点到汇点跑一边最大流即可
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<queue> 5 #include<algorithm> 6 using namespace std; 7 #define INF (1<<30) 8 #define MAXN 2222 9 #define MAXM 444*2222 10 11 struct Edge{ 12 int v,cap,flow,next; 13 }edge[MAXM]; 14 int vs,vt,NE,NV; 15 int head[MAXN]; 16 17 void addEdge(int u,int v,int cap){ 18 edge[NE].v=v; edge[NE].cap=cap; edge[NE].flow=0; 19 edge[NE].next=head[u]; head[u]=NE++; 20 edge[NE].v=u; edge[NE].cap=0; edge[NE].flow=0; 21 edge[NE].next=head[v]; head[v]=NE++; 22 } 23 24 int level[MAXN]; 25 int gap[MAXN]; 26 void bfs(){ 27 memset(level,-1,sizeof(level)); 28 memset(gap,0,sizeof(gap)); 29 level[vt]=0; 30 gap[level[vt]]++; 31 queue<int> que; 32 que.push(vt); 33 while(!que.empty()){ 34 int u=que.front(); que.pop(); 35 for(int i=head[u]; i!=-1; i=edge[i].next){ 36 int v=edge[i].v; 37 if(level[v]!=-1) continue; 38 level[v]=level[u]+1; 39 gap[level[v]]++; 40 que.push(v); 41 } 42 } 43 } 44 45 int pre[MAXN]; 46 int cur[MAXN]; 47 int ISAP(){ 48 bfs(); 49 memset(pre,-1,sizeof(pre)); 50 memcpy(cur,head,sizeof(head)); 51 int u=pre[vs]=vs,flow=0,aug=INF; 52 gap[0]=NV; 53 while(level[vs]<NV){ 54 bool flag=false; 55 for(int &i=cur[u]; i!=-1; i=edge[i].next){ 56 int v=edge[i].v; 57 if(edge[i].cap!=edge[i].flow && level[u]==level[v]+1){ 58 flag=true; 59 pre[v]=u; 60 u=v; 61 //aug=(aug==-1?edge[i].cap:min(aug,edge[i].cap)); 62 aug=min(aug,edge[i].cap-edge[i].flow); 63 if(v==vt){ 64 flow+=aug; 65 for(u=pre[v]; v!=vs; v=u,u=pre[u]){ 66 edge[cur[u]].flow+=aug; 67 edge[cur[u]^1].flow-=aug; 68 } 69 //aug=-1; 70 aug=INF; 71 } 72 break; 73 } 74 } 75 if(flag) continue; 76 int minlevel=NV; 77 for(int i=head[u]; i!=-1; i=edge[i].next){ 78 int v=edge[i].v; 79 if(edge[i].cap!=edge[i].flow && level[v]<minlevel){ 80 minlevel=level[v]; 81 cur[u]=i; 82 } 83 } 84 if(--gap[level[u]]==0) break; 85 level[u]=minlevel+1; 86 gap[level[u]]++; 87 u=pre[u]; 88 } 89 return flow; 90 } 91 int d[MAXN],low[366][1111]; 92 int main(){ 93 int n,m,a,b,c,l,r; 94 while(~scanf("%d%d",&n,&m)){ 95 memset(d,0,sizeof(d)); 96 int S=0,T=n+m+1; 97 vs=T+1; vt=vs+1; NV=vt+1; NE=0; 98 memset(head,-1,sizeof(head)); 99 for(int i=1; i<=m; ++i){ 100 scanf("%d",&a); 101 addEdge(i+n,T,INF); 102 d[T]-=a; 103 d[i+n]+=a; 104 } 105 memset(low,0,sizeof(low)); 106 vector<int> target[366]; 107 for(int i=1; i<=n; ++i){ 108 scanf("%d%d",&c,&a); 109 addEdge(S,i,a); 110 while(c--){ 111 scanf("%d%d%d",&a,&l,&r); 112 ++a; 113 target[i].push_back(a); low[i][a]=l; 114 addEdge(i,a+n,r-l); 115 d[a+n]-=l; 116 d[i]+=l; 117 } 118 } 119 int tag=NE; 120 addEdge(T,S,INF); 121 int tot=0; 122 for(int i=S; i<=T; ++i){ 123 if(d[i]<0) addEdge(vs,i,-d[i]); 124 else addEdge(i,vt,d[i]),tot+=d[i]; 125 } 126 tagEnd: 127 if(ISAP()!=tot){ 128 puts("-1\n"); 129 continue; 130 } 131 for(int i=tag; i<NE; ++i){ 132 edge[i].cap=edge[i].flow=0; 133 } 134 vs=S; vt=T; 135 ISAP(); 136 tot=0; 137 for(int i=head[vs]; i!=-1; i=edge[i].next){ 138 if(i&1) continue; 139 tot+=edge[i].flow; 140 } 141 printf("%d\n",tot); 142 for(int u=1; u<=n; ++u){ 143 for(int i=head[u]; i!=-1; i=edge[i].next){ 144 int v=edge[i].v-n; 145 if(i&1 || v<1 || v>m) continue; 146 low[u][v]+=edge[i].flow; 147 } 148 } 149 for(int u=1; u<=n; ++u){ 150 for(int i=0; i!=target[u].size(); ++i){ 151 printf("%d\n",low[u][target[u][i]]); 152 } 153 } 154 putchar('\n'); 155 } 156 return 0; 157 }