我爱网络流之最大流Dinic
直接上大佬博客:
模板步骤:
第一步,先bfs把图划分成分成分层图网络
第二步,dfs多次找增广路
当前弧优化:即每一次dfs增广时不从第一条边开始,而是用一个数组cur记录点u之前循环到了哪一条边,以此来加速
裸的最大流,直接按题意建图跑就行
1 #include<cstdio> 2 #include<queue> 3 #include<algorithm> 4 using namespace std; 5 const int N=218,inf=2000000007; 6 struct Side{ 7 int v,ne,w; 8 }S[N<<1]; 9 int n,sn,head[N],cur[N],dep[N]; 10 void init() 11 { 12 sn=0; 13 for(int i=0;i<=n;i++) 14 head[i]=-1; 15 } 16 void add(int u,int v,int w) 17 { 18 S[sn].v=v; 19 S[sn].w=w; 20 S[sn].ne=head[u]; 21 head[u]=sn++; 22 } 23 void addE(int u,int v,int w) 24 { 25 add(u,v,w); 26 add(v,u,0); 27 } 28 bool bfs() 29 { 30 queue<int> q; 31 for(int i=0;i<=n;i++) 32 dep[i]=0; 33 dep[1]=1; 34 q.push(1); 35 int x,y; 36 while(!q.empty()) 37 { 38 x=q.front(); 39 q.pop(); 40 for(int i=head[x];~i;i=S[i].ne) 41 { 42 y=S[i].v; 43 if(S[i].w>0&&!dep[y]) 44 { 45 dep[y]=dep[x]+1; 46 q.push(y); 47 } 48 } 49 } 50 return dep[n]!=0; 51 } 52 int dfs(int u,int minf) 53 { 54 if(u==n||!minf) 55 return minf; 56 int v,flow; 57 for(int &i=cur[u];~i;i=S[i].ne) 58 { 59 v=S[i].v; 60 if(dep[v]==dep[u]+1&&S[i].w>0) 61 { 62 flow=dfs(v,min(minf,S[i].w)); 63 if(flow) 64 { 65 S[i].w-=flow; 66 S[i^1].w+=flow; 67 return flow; 68 } 69 } 70 } 71 return 0; 72 } 73 int dinic() 74 { 75 int ans=0,flow; 76 while(bfs()) 77 { 78 for(int i=1;i<=n;i++) 79 cur[i]=head[i]; 80 while(flow=dfs(1,inf)) 81 ans+=flow; 82 } 83 return ans; 84 } 85 int main() 86 { 87 int m,u,v,w; 88 while(~scanf("%d%d",&m,&n)) 89 { 90 init(); 91 while(m--) 92 { 93 scanf("%d%d%d",&u,&v,&w); 94 addE(u,v,w); 95 } 96 printf("%d\n",dinic()); 97 } 98 return 0; 99 }
也是个裸的最大流,不过得看得出来,就把每周每天视为节点,然后弄个汇点跟源点,跑一遍dinic看最大流是不是总要求的天数
1 #include<cstdio> 2 #include<queue> 3 #include<algorithm> 4 using namespace std; 5 const int N=6118,inf=2000000007; 6 struct Side{ 7 int v,ne,w; 8 }S[N<<1]; 9 struct Film{ 10 int ok[8],day,week; 11 }F[N]; 12 int n,sn,sum,sb,se,head[N],cur[N],dep[N]; 13 void init() 14 { 15 sn=0,sum=0; 16 sb=0,se=n+351; 17 for(int i=0;i<=se;i++) 18 head[i]=-1; 19 } 20 void add(int u,int v,int w) 21 { 22 S[sn].v=v; 23 S[sn].w=w; 24 S[sn].ne=head[u]; 25 head[u]=sn++; 26 } 27 void addE(int u,int v,int w) 28 { 29 add(u,v,w); 30 add(v,u,0); 31 } 32 bool bfs() 33 { 34 queue<int> q; 35 for(int i=0;i<=se;i++) 36 dep[i]=0; 37 dep[sb]=1; 38 q.push(sb); 39 int u,v; 40 while(!q.empty()) 41 { 42 u=q.front(); 43 q.pop(); 44 for(int i=head[u];~i;i=S[i].ne) 45 { 46 v=S[i].v; 47 if(S[i].w>0&&!dep[v]) 48 { 49 dep[v]=dep[u]+1; 50 q.push(v); 51 } 52 } 53 } 54 return dep[se]!=0; 55 } 56 int dfs(int u,int minf) 57 { 58 if(u==se||!minf) 59 return minf; 60 int v,flow; 61 for(int &i=cur[u];~i;i=S[i].ne) 62 { 63 v=S[i].v; 64 if(S[i].w>0&&dep[v]==dep[u]+1) 65 { 66 flow=dfs(v,min(minf,S[i].w)); 67 if(flow>0) 68 { 69 S[i].w-=flow; 70 S[i^1].w+=flow; 71 return flow; 72 } 73 } 74 } 75 return 0; 76 } 77 int dinic() 78 { 79 int ans=0,flow; 80 while(bfs()) 81 { 82 for(int i=0;i<=se;i++) 83 cur[i]=head[i]; 84 while(flow=dfs(sb,inf)) 85 ans+=flow; 86 } 87 return ans; 88 } 89 int main() 90 { 91 int t; 92 scanf("%d",&t); 93 while(t--) 94 { 95 scanf("%d",&n); 96 init(); 97 for(int i=1;i<=n;i++) 98 { 99 for(int j=1;j<=7;j++) 100 scanf("%d",&F[i].ok[j]); 101 scanf("%d%d",&F[i].day,&F[i].week); 102 sum+=F[i].day; 103 } 104 for(int i=1;i<=n;i++) 105 addE(sb,i,F[i].day); 106 for(int i=1;i<=n;i++) 107 { 108 for(int j=0;j<F[i].week;j++) 109 for(int k=1;k<=7;k++) 110 if(F[i].ok[k]) 111 addE(i,n+j*7+k,1); 112 } 113 for(int i=0;i<50;i++) 114 for(int j=1;j<=7;j++) 115 addE(n+i*7+j,se,1); 116 if(dinic()>=sum) 117 printf("Yes\n"); 118 else 119 printf("No\n"); 120 } 121 return 0; 122 }
100000个人,但才10个星球,在建图上,把可以去的星球状态相同的人视为一样的,这样最多就才1024个状态,然后跑一遍dinic,c++直接交,g++的话得用快读。
1 #include<cstdio> 2 #include<queue> 3 #include<algorithm> 4 using namespace std; 5 const int N=1<<12,inf=1000000007; 6 struct Side{ 7 int v,ne,w; 8 }S[N<<2]; 9 int sn,pb,pe,n,m,head[N],cur[N]; 10 int cf2[12]={1},man[N],dep[N]; 11 //int read() 12 //{ 13 // int res = 0, flg = 1; char chr = getchar(); 14 // while(chr < '0' || chr > '9') {if(chr == '-') res = -1; chr = getchar();} 15 // while(chr <= '9' && chr >= '0') {res = res * 10 + chr - '0'; chr = getchar();} 16 // return res * flg; 17 //}g++用快读 18 void init() 19 { 20 sn=0; 21 pb=0,pe=cf2[m]+m; 22 for(int i=0;i<cf2[m];i++) 23 man[i]=0; 24 for(int i=0;i<=pe;i++) 25 head[i]=-1; 26 } 27 void add(int u,int v,int w) 28 { 29 S[sn].w=w; 30 S[sn].v=v; 31 S[sn].ne=head[u]; 32 head[u]=sn++; 33 } 34 void addE(int u,int v,int w) 35 { 36 add(u,v,w); 37 add(v,u,0); 38 } 39 bool bfs() 40 { 41 for(int i=0;i<=pe;i++) 42 dep[i]=0; 43 dep[pb]=1; 44 queue<int> q; 45 q.push(pb); 46 int u,v; 47 while(!q.empty()) 48 { 49 u=q.front(); 50 q.pop(); 51 for(int i=head[u];~i;i=S[i].ne) 52 { 53 v=S[i].v; 54 if(S[i].w>0&&!dep[v]) 55 { 56 dep[v]=dep[u]+1; 57 q.push(v); 58 } 59 } 60 } 61 return dep[pe]!=0; 62 } 63 int dfs(int u,int minf) 64 { 65 if(u==pe||!minf) 66 return minf; 67 int v,flow; 68 for(int &i=cur[u];~i;i=S[i].ne) 69 { 70 v=S[i].v; 71 if(S[i].w>0&&dep[v]==dep[u]+1) 72 { 73 flow=dfs(v,min(minf,S[i].w)); 74 if(flow) 75 { 76 S[i].w-=flow; 77 S[i^1].w+=flow; 78 return flow; 79 } 80 } 81 } 82 return 0; 83 } 84 int dinic() 85 { 86 int maxf=0,flow; 87 while(bfs()) 88 { 89 for(int i=0;i<=pe;i++) 90 cur[i]=head[i]; 91 while(flow=dfs(pb,inf)) 92 maxf+=flow; 93 } 94 return maxf; 95 } 96 int main() 97 { 98 for(int i=1;i<=10;i++) 99 cf2[i]=cf2[i-1]<<1; 100 int num,x; 101 while(~scanf("%d%d",&n,&m)) 102 { 103 init(); 104 for(int i=1;i<=n;i++) 105 { 106 num=0; 107 for(int j=0;j<m;j++) 108 { 109 scanf("%d",&x); 110 if(x) 111 num|=cf2[j]; 112 } 113 man[num]++; 114 } 115 for(int i=1;i<cf2[m];i++) 116 if(man[i]) 117 { 118 addE(pb,i,man[i]); 119 for(int j=0;j<m;j++) 120 if(i&cf2[j]) 121 addE(i,cf2[m]+j,man[i]); 122 } 123 for(int i=0;i<m;i++) 124 { 125 scanf("%d",&x); 126 addE(cf2[m]+i,pe,x); 127 } 128 if(dinic()>=n) 129 printf("YES\n"); 130 else 131 printf("NO\n"); 132 } 133 return 0; 134 }
啊,网络流就在于建图。
我太难了~给个三连吧,亲~~~