1. 程式人生 > >網路流題目彙總

網路流題目彙總

最大流

Poj 1149 PIGS
為了保證順序,可以建n列m排點,每個人連ki到T,豬圈連在一起,依次決策。

點數nm。

其實可以更好。

發現其實很多點都是不變的,這樣很浪費。

考慮分配的原因,本質是為了後面的人的選擇。

所以,

源點到每個豬圈來買的第一個人連一條容量為該豬圈裡豬的數量的邊
對於每個豬圈,第i個來買的人向第i+1個來買的人連一條容量為正無窮的邊
每個人向匯點連一條容量為購買數量的邊

這樣,每個人的面對的豬圈要麼是沒有動過的,要麼是可能經過之前分配過的。符合題意。

人之間可以直接傳遞豬。就不用豬圈了。

點數n

注意n,m輸入,先m後n。

#include<cstdio>
#include
<cstdlib> #include<algorithm> #include<cstring> #include<iostream> #define il inline #define reg register int #define numb (ch^'0') using namespace std; typedef long long ll; il void rd(int &x){ char ch;bool fl=false; while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true
); for(x=numb;isdigit(ch=getchar());x=x*10+numb); (fl==true)&&(x=-x); } namespace Miracle{ const int N=105; const int M=1005; const int inf=0x3f3f3f3f; int n,m; struct node{ int nxt,to; int w; }e[N*M*2+M*2]; int s,t; int hd[N],cnt=1; void add(int x,int y,int z){ e[++cnt].nxt=hd[x]; e[cnt].to
=y; e[cnt].w=z; hd[x]=cnt; e[++cnt].nxt=hd[y]; e[cnt].to=x; e[cnt].w=0; hd[y]=cnt; } int pig[M],vis[M]; int las[M];//las has i 's ren int d[N+3]; int dfs(int x,int flow){ int res=flow; if(x==t) return flow; for(reg i=hd[x];i&&res;i=e[i].nxt){ int y=e[i].to; if(d[y]==d[x]+1&&e[i].w){ int k=dfs(y,min(res,e[i].w)); if(!k) d[y]=0; e[i].w-=k; e[i^1].w+=k; res-=k; } } return flow-res; } int q[N+3]; int l,r; bool bfs(){ l=1,r=0; memset(d,0,sizeof d); q[++r]=s; d[s]=1; while(l<=r){ int x=q[l++]; for(reg i=hd[x];i;i=e[i].nxt){ int y=e[i].to; if(e[i].w&&!d[y]){ d[y]=d[x]+1; q[++r]=y; if(y==t) return true; } } } return false; } int main(){ rd(m);rd(n); for(reg i=1;i<=m;++i) rd(pig[i]); int x,c; s=0,t=n+1; for(reg i=1;i<=n;++i){ rd(c); while(c--){ rd(x); if(!las[x]) add(s,i,pig[x]),las[x]=i; else add(las[x],i,inf),las[x]=i; } rd(c); add(i,t,c); } int flow=0; int ans=0; while(bfs()){ while(flow=dfs(s,inf)) ans+=flow; } printf("%d",ans); return 0; } } signed main(){ Miracle::main(); return 0; } /* Author: *Miracle* Date: 2018/12/14 7:58:25 */
View Code