最大流
刚刚学了两个最大流算法Dinic和ISAP,很多地方不是很清楚=_=||
先刷些题练练吧
Drainage Ditches
HDU - 1532可以说是模板题了,用Dinic做的
我把Lrj的模板改了下,个人不太喜欢用vector==
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define CLR(m,a) memset(m,a,sizeof(m)) 4 const int inf=0x3f3f3f3f; 5 const int maxv=210; 6 int n,m; 7 struct Edge 8 { 9 int u,v,cap,flow; 10 int nex; 11 }e[maxv<<1]; 12 int head[maxv]; 13 int cnt=0; 14 void init() 15 { 16 CLR(head,-1); 17 cnt=0; 18 } 19 void add(int u,int v,int cap) 20 { 21 e[cnt].u=u; 22 e[cnt].v=v; 23 e[cnt].cap=cap; 24 e[cnt].flow=0; 25 e[cnt].nex=head[u]; 26 head[u]=cnt++; 27 } 28 29 int vis[maxv],d[maxv],cur[maxv]; 30 int s,t; 31 int bfs() 32 { 33 CLR(vis,0); 34 queue<int> q; 35 q.push(s); 36 d[s]=0; 37 vis[s]=1; 38 while(!q.empty()) 39 { 40 int u=q.front(); 41 q.pop(); 42 for(int i=head[u];~i;i=e[i].nex) 43 { 44 int v=e[i].v; 45 if(!vis[v]&&e[i].cap>e[i].flow) 46 { 47 vis[v]=1; 48 d[v]=d[u]+1; 49 q.push(v); 50 } 51 } 52 } 53 return vis[t]; 54 } 55 56 int dfs(int x,int a) 57 { 58 if(x==t||a==0) return a; 59 int flow=0,f; 60 for(int &i=cur[x];~i;i=e[i].nex) 61 { 62 int v=e[i].v; 63 if(d[x]+1==d[v]&&(f=dfs(v,min(a,e[i].cap-e[i].flow)))>0) 64 { 65 e[i].flow+=f; 66 e[i^1].flow-=f; 67 flow+=f; 68 a-=f; 69 if(a==0) break; 70 } 71 } 72 return flow; 73 } 74 75 int Maxflow() 76 { 77 int flow=0; 78 while(bfs()) 79 { 80 for(int i=0;i<n;i++) cur[i]=head[i]; 81 flow+=dfs(s,inf); 82 } 83 return flow; 84 } 85 86 int main() 87 { 88 while(scanf("%d%d",&m,&n)!=EOF) 89 { 90 init(); 91 int u,v,cap; 92 for(int i=0;i<m;i++) 93 { 94 scanf("%d%d%d",&u,&v,&cap); 95 u--;v--; 96 add(u,v,cap); 97 add(v,u,0); 98 } 99 s=0;t=n-1; // 100 printf("%d\n",Maxflow()); 101 } 102 }
Flow Problem
HDU - 3549本来想着练习一下ISPA
结果。。悲剧了一晚上。。。
代码里面有注释,关键点在更新m时判断一下d[v]是否可达,lrj的书里面没提到。。。
好像跟d的初始化有关。。。
再加上我用前向星存的边,出了点差错,单行调试了一上午才发现=_=||
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define CLR(m,a) memset(m,a,sizeof(m)) 4 const int inf=0x3f3f3f3f; 5 const int maxv=20; 6 const int maxe=1010; 7 int n,m; 8 struct Edge 9 { 10 int u,v,cap,flow; 11 int nex; 12 }e[maxe<<1]; 13 int head[maxv]; 14 int cnt=0; 15 void init() 16 { 17 CLR(head,-1); 18 cnt=0; 19 } 20 void add(int u,int v,int cap) 21 { 22 e[cnt].u=u; 23 e[cnt].v=v; 24 e[cnt].cap=cap; 25 e[cnt].flow=0; 26 e[cnt].nex=head[u]; 27 head[u]=cnt++; 28 } 29 30 int p[maxv]; // 可增广路上的上一条弧的编号 31 int num[maxv]; // 和 t 的最短距离等于 i 的节点数量 32 int cur[maxv];// 当前弧下标 33 int d[maxv]; // 残量网络中节点 i 到汇点 t 的最短距离 34 int vis[maxv]; 35 int s,t; 36 37 // 预处理, 反向 BFS 构造 d 数组 38 int bfs() 39 { 40 CLR(vis,0); 41 CLR(d,-1); 42 queue<int> q; 43 while(!q.empty()) q.pop(); 44 q.push(t); 45 vis[t]=1; 46 d[t]=0; 47 while(!q.empty()) 48 { 49 int u=q.front(); 50 q.pop(); 51 for(int i=head[u];~i;i=e[i].nex) 52 { 53 int id=i&(-2); 54 int v=e[id].u; 55 if(!vis[v]&&e[id].cap>e[id].flow) 56 { 57 vis[v]=1; 58 d[v]=d[u]+1; 59 q.push(v); 60 } 61 } 62 } 63 return vis[s]; 64 } 65 66 //增广 67 int augment() 68 { 69 int u=t,a=inf; 70 while(u!=s) 71 { 72 int id=p[u]; 73 a=min(a,e[id].cap-e[id].flow); 74 u=e[id].u; 75 } 76 u=t; 77 while(u!=s) 78 { 79 int id=p[u]; 80 e[id].flow+=a; 81 e[id^1].flow-=a; 82 u=e[id].u; 83 } 84 return a; 85 } 86 87 int Maxflow() 88 { 89 bfs(); 90 int flow=0; 91 CLR(num,0); 92 for(int i=0;i<n;i++) num[d[i]]++; 93 int u=s; 94 for(int i=0;i<n;i++) cur[i]=head[i]; 95 while(d[s]<n) 96 { 97 if(u==t) 98 { 99 flow+=augment(); 100 u=s; 101 } 102 int ok=0; 103 for(int i=cur[u];~i;i=e[i].nex) 104 { 105 int v=e[i].v; 106 if(e[i].cap>e[i].flow&&d[u]==d[v]+1) 107 { 108 ok=1; 109 p[v]=i; 110 cur[u]=i; 111 u=v; 112 break; 113 } 114 } 115 if(!ok) 116 { 117 int m=n-1; 118 for(int i=head[u];~i;i=e[i].nex) 119 { 120 int v=e[i].v; 121 if(e[i].cap>e[i].flow&&d[v]!=-1) m=min(m,d[v]); 122 } 123 if(--num[d[u]]==0) break; //gap优化 124 num[d[u]=m+1]++; 125 cur[u]=head[u]; 126 if(u!=s) u=e[p[u]].u; 127 } 128 } 129 return flow; 130 } 131 132 int main() 133 { 134 int tt; 135 int kase=0; 136 scanf("%d",&tt); 137 while(tt--) 138 { 139 init(); 140 int u,v,cap; 141 scanf("%d%d",&n,&m); 142 for(int i=0;i<m;i++) 143 { 144 scanf("%d%d%d",&u,&v,&cap); 145 u--;v--; 146 add(u,v,cap); 147 add(v,u,0); 148 } 149 s=0;t=n-1; 150 printf("Case %d: %d\n",++kase,Maxflow()); 151 } 152 }
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define CLR(m,a) memset(m,a,sizeof(m)) 4 const int inf=0x3f3f3f3f; 5 const int maxv=20; 6 const int maxe=1010; 7 int n,m; 8 struct Edge 9 { 10 int u,v,cap,flow; 11 int nex; 12 }e[maxe<<1]; 13 int head[maxv]; 14 int cnt=0; 15 void init() 16 { 17 CLR(head,-1); 18 cnt=0; 19 } 20 void add(int u,int v,int cap) 21 { 22 e[cnt].u=u; 23 e[cnt].v=v; 24 e[cnt].cap=cap; 25 e[cnt].flow=0; 26 e[cnt].nex=head[u]; 27 head[u]=cnt++; 28 } 29 30 int p[maxv]; // 可增广路上的上一条弧的编号 31 int num[maxv]; // 和 t 的最短距离等于 i 的节点数量 32 int cur[maxv];// 当前弧下标 33 int d[maxv]; // 残量网络中节点 i 到汇点 t 的最短距离 34 int vis[maxv]; 35 int s,t; 36 37 // 预处理, 反向 BFS 构造 d 数组 38 int bfs() 39 { 40 CLR(vis,0); 41 // CLR(d,-1); //!!! 42 queue<int> q; 43 while(!q.empty()) q.pop(); 44 q.push(t); 45 vis[t]=1; 46 d[t]=0; 47 while(!q.empty()) 48 { 49 int u=q.front(); 50 q.pop(); 51 for(int i=head[u];~i;i=e[i].nex) 52 { 53 int id=i&(-2); 54 int v=e[id].u; 55 if(!vis[v]&&e[id].cap>e[id].flow) 56 { 57 vis[v]=1; 58 d[v]=d[u]+1; 59 q.push(v); 60 } 61 } 62 } 63 return vis[s]; 64 } 65 66 //增广 67 int augment() 68 { 69 int u=t,a=inf; 70 while(u!=s) 71 { 72 int id=p[u]; 73 a=min(a,e[id].cap-e[id].flow); 74 u=e[id].u; 75 } 76 u=t; 77 while(u!=s) 78 { 79 int id=p[u]; 80 e[id].flow+=a; 81 e[id^1].flow-=a; 82 u=e[id].u; 83 } 84 return a; 85 } 86 87 int Maxflow() 88 { 89 bfs(); 90 int flow=0; 91 CLR(num,0); 92 for(int i=0;i<n;i++) num[d[i]]++; 93 int u=s; 94 for(int i=0;i<n;i++) cur[i]=head[i]; 95 while(d[s]<n) 96 { 97 if(u==t) 98 { 99 flow+=augment(); 100 u=s; 101 } 102 int ok=0; 103 for(int i=cur[u];~i;i=e[i].nex) 104 { 105 int v=e[i].v; 106 if(e[i].cap>e[i].flow&&d[u]==d[v]+1) 107 { 108 ok=1; 109 p[v]=i; 110 cur[u]=i; 111 u=v; 112 break; 113 } 114 } 115 if(!ok) 116 { 117 int m=n-1; 118 for(int i=head[u];~i;i=e[i].nex) 119 { 120 int v=e[i].v; 121 if(e[i].cap>e[i].flow/*&&d[v]!=-1*/) m=min(m,d[v]); //关键点!!!注释掉就错啦 122 } 123 if(--num[d[u]]==0) break; //gap优化 124 num[d[u]=m+1]++; 125 cur[u]=head[u]; 126 if(u!=s) u=e[p[u]].u; 127 } 128 } 129 return flow; 130 } 131 132 int main() 133 { 134 int tt; 135 int kase=0; 136 scanf("%d",&tt); 137 while(tt--) 138 { 139 init(); 140 int u,v,cap; 141 scanf("%d%d",&n,&m); 142 for(int i=0;i<m;i++) 143 { 144 scanf("%d%d%d",&u,&v,&cap); 145 u--;v--; 146 add(u,v,cap); 147 add(v,u,0); 148 } 149 s=0;t=n-1; 150 printf("Case %d: %d\n",++kase,Maxflow()); 151 } 152 } 153 /* 154 5 6 155 1 2 40 156 1 5 20 157 2 5 20 158 2 3 30 159 3 5 10 160 2 4 10 161 */
补一个低效但相对简单易懂的算法Edmonds-Karp
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxv=20; 4 const int maxe=1010; 5 const int inf=0x3f3f3f3f; 6 #define CLR(m,a) memset(m,a,sizeof(m)) 7 int n,m; 8 struct Edge 9 { 10 int u,v,cap,flow; 11 int nex; 12 }e[maxe<<1]; 13 int head[maxv]; 14 int cnt=0; 15 void init() 16 { 17 CLR(head,-1); 18 cnt=0; 19 } 20 void add(int u,int v,int cap) 21 { 22 e[cnt].u=u; 23 e[cnt].v=v; 24 e[cnt].flow=0; 25 e[cnt].cap=cap; 26 e[cnt].nex=head[u]; 27 head[u]=cnt++; 28 } 29 int s,t; 30 int a[maxv],p[maxv]; 31 int EK() 32 { 33 int flow=0; 34 for(;;) 35 { 36 CLR(a,0); 37 queue<int> q; 38 q.push(s); 39 a[s]=inf; 40 while(!q.empty()) 41 { 42 int u=q.front(); 43 q.pop(); 44 for(int i=head[u];~i;i=e[i].nex) 45 { 46 int v=e[i].v; 47 if(!a[v]&&e[i].cap>e[i].flow) 48 { 49 p[v]=i; 50 a[v]=min(a[u],e[i].cap-e[i].flow); 51 q.push(v); 52 } 53 } 54 if(a[t]) break; 55 } 56 if(!a[t]) break; 57 for(int u=t;u!=s;u=e[p[u]].u) 58 { 59 e[p[u]].flow+=a[t]; 60 e[p[u]^1].flow-=a[t]; 61 } 62 flow+=a[t]; 63 } 64 return flow; 65 } 66 int main() 67 { 68 int tt; 69 int kase=0; 70 scanf("%d",&tt); 71 while(tt--) 72 { 73 init(); 74 int u,v,cap; 75 scanf("%d%d",&n,&m); 76 for(int i=0;i<m;i++) 77 { 78 scanf("%d%d%d",&u,&v,&cap); 79 u--;v--; 80 add(u,v,cap); 81 add(v,u,0); 82 } 83 s=0;t=n-1; 84 printf("Case %d: %d\n",++kase,EK()); 85 } 86 }
Task Schedule
HDU - 3572加超级源和超级汇
本来建图能力就差,根本没想到
超级源到每一个零件连一条权重为pi的边,每个零件到可以加工的时间(每一天)连一条为1的边
时间(每一天)到超级汇连一条为m的边
其实还是比较好理解的
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define CLR(m,a) memset(m,a,sizeof(m)) 4 const int inf=0x3f3f3f3f; 5 const int maxv=510; 6 int n,m; 7 struct Edge 8 { 9 int u,v,cap,flow; 10 int nex; 11 }e[(maxv*maxv<<1)+2010]; 12 int head[maxv<<1]; 13 int cnt=0; 14 void init() 15 { 16 CLR(head,-1); 17 cnt=0; 18 } 19 void add(int u,int v,int cap) 20 { 21 e[cnt].u=u; 22 e[cnt].v=v; 23 e[cnt].cap=cap; 24 e[cnt].flow=0; 25 e[cnt].nex=head[u]; 26 head[u]=cnt++; 27 } 28 int num[maxv<<1],d[maxv<<1],p[maxv<<1],vis[maxv<<1],cur[maxv<<1]; 29 int s,t; 30 int bfs() 31 { 32 CLR(vis,0); 33 CLR(d,-1); 34 queue<int> q; 35 q.push(t); 36 d[t]=0; 37 vis[t]=1; 38 while(!q.empty()) 39 { 40 int u=q.front(); 41 q.pop(); 42 for(int i=head[u];~i;i=e[i].nex) 43 { 44 int id=i&(-2); 45 int v=e[id].u; 46 if(!vis[v]&&e[id].cap>e[id].flow) 47 { 48 vis[v]=1; 49 d[v]=d[u]+1; 50 q.push(v); 51 } 52 } 53 } 54 return vis[s]; 55 } 56 int augment() 57 { 58 int u=t,a=inf; 59 while(u!=s) 60 { 61 int id=p[u]; 62 a=min(a,e[id].cap-e[id].flow); 63 u=e[id].u; 64 } 65 u=t; 66 while(u!=s) 67 { 68 int id=p[u]; 69 e[id].flow+=a; 70 e[id^1].flow-=a; 71 u=e[id].u; 72 } 73 return a; 74 } 75 int ISAP() 76 { 77 bfs(); 78 int flow=0; 79 CLR(num,0); 80 for(int i=0;i<n;i++) num[d[i]]++; 81 for(int i=0;i<n;i++) cur[i]=head[i]; 82 int u=s; 83 while(d[s]<n) 84 { 85 if(u==t) 86 { 87 flow+=augment(); 88 u=s; 89 } 90 int ok=0; 91 for(int i=cur[u];~i;i=e[i].nex) 92 { 93 int v=e[i].v; 94 if(e[i].cap>e[i].flow&&d[u]==d[v]+1) 95 { 96 ok=1; 97 p[v]=i; 98 cur[u]=i; 99 u=v; 100 break; 101 } 102 } 103 if(!ok) 104 { 105 int m=n-1; 106 for(int i=head[u];~i;i=e[i].nex) 107 if(e[i].cap>e[i].flow&&d[e[i].v]!=-1) m=min(m,d[e[i].v]); 108 if(--num[d[u]]==0) break; 109 num[d[u]=m+1]++; 110 cur[u]=head[u]; 111 if(u!=s) u=e[p[u]].u; 112 } 113 } 114 return flow; 115 } 116 int main() 117 { 118 int tt; 119 int kase=0; 120 scanf("%d",&tt); 121 while(tt--) 122 { 123 init(); 124 int si,pi,ei; 125 int sum=0; 126 int maxt=0; 127 s=0; 128 scanf("%d%d",&n,&m); 129 for(int i=1;i<=n;i++) 130 { 131 scanf("%d%d%d",&pi,&si,&ei); 132 maxt=max(maxt,ei); 133 sum+=pi; 134 add(s,i,pi); 135 add(i,s,0); 136 for(int j=si;j<=ei;j++) 137 { 138 add(i,n+j,1); 139 add(j+n,i,0); 140 } 141 } 142 t=n+maxt+1; 143 for(int i=1;i<=maxt;i++) 144 { 145 add(i+n,t,m); 146 add(t,i+n,0); 147 } 148 n=t+1; //此处修改n值以适应模板 149 printf("Case %d: ",++kase); 150 if(ISAP()==sum) puts("Yes\n"); 151 else puts("No\n"); 152 } 153 }
Leapin' Lizards
题意:在一个网格状的区域内,有一些柱子,并且这些柱子有一定的允许跳跃次数,有的柱子上有人,人有最大跳跃距离(曼哈顿距离)
问有几个人无法跳出此区域
还是不会建图啊,拆点!!!
增加超级源和超级汇
对于每一个人,从超级源到人连一条为1的边,对于任意两个可达的柱子,连一条无穷大的边,可跳出区域的柱子连一条无穷大的边到超级汇
然后拆点,把每个柱子拆成两个,连一条为跳跃次数的边。
拆点的意义在于限流!!!
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int inf=0x3f3f3f3f; 4 const int maxv=1010; 5 const int maxe=1000010; 6 #define CLR(m,a) memset(m,a,sizeof(m)) 7 #define LL long long 8 9 struct Edge 10 { 11 int u,v,cap,flow; 12 int nex; 13 }e[maxe<<1]; 14 int head[maxv]; 15 int cnt=0; 16 void init() 17 { 18 CLR(head,-1); 19 cnt=0; 20 } 21 void add(int u,int v,int cap) 22 { 23 e[cnt].u=u; e[cnt].v=v; 24 e[cnt].cap=cap; e[cnt].flow=0; 25 e[cnt].nex=head[u]; head[u]=cnt++; 26 27 e[cnt].u=v; e[cnt].v=u; 28 e[cnt].cap=0; e[cnt].flow=0; 29 e[cnt].nex=head[v]; head[v]=cnt++; 30 } 31 char g1[25][25],g2[25][25]; 32 33 int n; 34 int s,t; 35 int p[maxv],cur[maxv],d[maxv],vis[maxv],num[maxv]; 36 void bfs() 37 { 38 CLR(vis,0); 39 CLR(d,-1); 40 queue<int> q; 41 q.push(t); 42 d[t]=0; 43 vis[t]=1; 44 while(!q.empty()) 45 { 46 int u=q.front(); 47 q.pop(); 48 for(int i=head[u];~i;i=e[i].nex) 49 { 50 int id=i&(-2); 51 int v=e[id].u; 52 if(!vis[v]&&e[id].cap>e[id].flow) 53 { 54 d[v]=d[u]+1; 55 vis[v]=1; 56 q.push(v); 57 } 58 } 59 } 60 } 61 int augment() 62 { 63 int u=t,a=inf; 64 while(u!=s) 65 { 66 int id=p[u]; 67 a=min(a,e[id].cap-e[id].flow); 68 u=e[id].u; 69 } 70 u=t; 71 while(u!=s) 72 { 73 int id=p[u]; 74 e[id].flow+=a; 75 e[id^1].flow-=a; 76 u=e[id].u; 77 } 78 return a; 79 } 80 int ISAP() 81 { 82 int flow=0; 83 bfs(); 84 CLR(num,0); 85 for(int i=0;i<n;i++){ 86 num[d[i]]++; 87 cur[i]=head[i]; 88 } 89 int u=s; 90 while(d[s]<n){ 91 if(u==t){ 92 flow+=augment(); 93 u=s; 94 } 95 int ok=0; 96 for(int i=cur[u];~i;i=e[i].nex){ 97 int v=e[i].v; 98 if(e[i].cap>e[i].flow&&d[u]==d[v]+1){ 99 ok=1; 100 p[v]=i; 101 cur[u]=i; 102 u=v; 103 break; 104 } 105 } 106 if(!ok){ 107 int m=n-1; 108 for(int i=head[u];~i;i=e[i].nex){ 109 int v=e[i].v; 110 if(e[i].cap>e[i].flow&&d[v]!=-1) m=min(m,d[v]); 111 } 112 if(--num[d[u]]==0) break; 113 num[d[u]=m+1]++; 114 cur[u]=head[u]; 115 if(u!=s) u=e[p[u]].u; 116 } 117 } 118 return flow; 119 } 120 int main() 121 { 122 int tt; 123 int kase=0; 124 scanf("%d",&tt); 125 while(tt--){ 126 init(); 127 int r,c,dis; 128 int sum=0; 129 scanf("%d%d",&r,&dis); 130 for(int i=0;i<r;i++){ 131 scanf("%s",g1[i]); 132 } 133 for(int i=0;i<r;i++){ 134 scanf("%s",g2[i]); 135 } 136 c=strlen(g1[0]); 137 int py=r*c; //拆点 138 s=0; 139 for(int i=0;i<r;i++){ 140 for(int j=0;j<c;j++){ 141 int id=i*c+j+1; 142 if(g2[i][j]=='L'){ 143 sum++; 144 add(s,id,1); 145 } 146 if(g1[i][j]!='0'){ 147 add(id,id+py,g1[i][j]-'0'); 148 if(i-dis<0||i+dis>=r||j-dis<0||j+dis>=c){ 149 add(id+py,py*2+1,inf); 150 } 151 else{ 152 for(int x=0;x<r;x++) 153 for(int y=0;y<c;y++){ 154 if(x==i&&y==j) continue; 155 if(g1[x][y]!='0'){ 156 if(abs(x-i)+abs(y-j)<=dis){ 157 int newid=x*c+y+1; 158 add(id+py,newid,inf); 159 } 160 } 161 } 162 } 163 } 164 } 165 } 166 s=0;t=py*2+1;n=t+1; //!!! 167 int flow=ISAP(); 168 printf("Case #%d: ",++kase); 169 if(flow==sum) puts("no lizard was left behind."); 170 else if(flow+1==sum) puts("1 lizard was left behind."); 171 else printf("%d lizards were left behind.\n",sum-flow); 172 } 173 return 0; 174 }
Kakuro Extension
TLE到爆炸!!!很烦!!!实在看不下去了。。。。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int inf=0x3f3f3f3f; 4 const int maxv=200010; 5 const int maxe=1000010; // 6 #define CLR(m,a) memset(m,a,sizeof(m)) 7 8 int n,m,s,t; 9 int tot; 10 struct Edge{ 11 int u,v,cap,flow; 12 int nex; 13 }e[maxe]; 14 int head[maxv]; 15 int cnt=0; 16 void init(){ 17 CLR(head,-1); 18 cnt=0; 19 } 20 void add(int u,int v,int cap) 21 { 22 e[cnt].u=u; e[cnt].v=v; 23 e[cnt].cap=cap; e[cnt].flow=0; 24 e[cnt].nex=head[u]; head[u]=cnt++; 25 26 e[cnt].u=v; e[cnt].v=u; 27 e[cnt].cap=0; e[cnt].flow=0; 28 e[cnt].nex=head[v]; head[v]=cnt++; 29 } 30 struct node{ 31 int id,cid,rid,sumc,sumr,type; 32 }mp[105][105]; 33 int ans[105][105]; //记录该点的出边,便于输出 34 35 int vis[maxv],cur[maxv],num[maxv],d[maxv],p[maxv]; 36 37 void bfs(){ 38 CLR(d,-1); 39 CLR(vis,0); 40 queue<int> q; 41 q.push(t); 42 d[t]=0; 43 vis[t]=1; 44 while(!q.empty()){ 45 int u=q.front(); 46 q.pop(); 47 for(int i=head[u];~i;i=e[i].nex){ 48 int id=i&(-2); 49 int v=e[id].u; 50 if(!vis[v]&&e[id].cap>e[id].flow){ 51 vis[v]=1; 52 q.push(v); 53 d[v]=d[u]+1; 54 } 55 } 56 } 57 } 58 int augment(){ 59 int a=inf,u=t; 60 while(u!=s){ 61 int id=p[u]; 62 a=min(a,e[id].cap-e[id].flow); 63 u=e[id].u; 64 } 65 u=t; 66 while(u!=s){ 67 int id=p[u]; 68 e[id].flow+=a; 69 e[id^1].flow-=a; 70 u=e[id].u; 71 } 72 return a; 73 } 74 int ISAP(){ 75 bfs(); 76 int flow=0; 77 CLR(num,0); 78 for(int i=0;i<tot;i++){ 79 num[d[i]]++; 80 cur[i]=head[i]; 81 } 82 int u=s; 83 while(d[s]<tot) 84 { 85 if(u==t) 86 { 87 flow+=augment(); 88 u=s; 89 } 90 int ok=0; 91 for(int i=cur[u];~i;i=e[i].nex){ 92 int v=e[i].v; 93 if(e[i].cap>e[i].flow&&d[u]==d[v]+1){ 94 ok=1; 95 cur[u]=i; 96 p[v]=i; 97 u=v; 98 break; 99 } 100 } 101 if(!ok){ 102 int m=tot-1; 103 if(--num[d[u]]==0) break; 104 for(int i=head[u];~i;i=e[i].nex){ 105 int v=e[i].v; 106 if(e[i].cap>e[i].flow&&d[v]!=-1) m=min(m,d[v]); 107 } 108 num[d[u]=m+1]++; 109 cur[u]=head[u]; 110 if(u!=s) u=e[p[u]].u; 111 } 112 } 113 return flow; 114 } 115 116 int main(){ 117 while(scanf("%d%d",&n,&m)!=EOF){ 118 init(); 119 char c[10]; 120 int rowcnt=0,colcnt=0,white=0; 121 for(int i=0;i<n;i++) 122 for(int j=0;j<m;j++){ 123 scanf("%s",c); 124 if(c[3]=='X') continue; 125 else if(c[3]=='.'){ 126 white++; 127 mp[i][j].type=2; 128 mp[i][j].id=white; 129 } 130 else{ 131 mp[i][j].type=1; 132 int num; 133 if(c[0]!='X'){ 134 num=(c[0]-'0')*100+(c[1]-'0')*10+c[2]-'0'; 135 colcnt++; 136 mp[i][j].cid=colcnt; 137 mp[i][j].sumc=num; 138 } 139 if(c[4]!='X'){ 140 num=(c[4]-'0')*100+(c[5]-'0')*10+c[6]-'0'; 141 rowcnt++; 142 mp[i][j].rid=rowcnt; 143 mp[i][j].sumr=num; 144 } 145 } 146 } 147 s=0;t=white+rowcnt+colcnt+1; 148 tot=t+1; 149 //编点,white<colcnt<rowcnt 150 for(int i=0;i<n;i++) 151 for(int j=0;j<m;j++){ 152 if(mp[i][j].type==1){ 153 if(mp[i][j].sumc>0){ //如果列有数字 154 int id=mp[i][j].cid+white; 155 for(int k=i+1;k<n;k++){ 156 if(mp[k][j].type==2){ 157 add(id,mp[k][j].id,8); 158 mp[i][j].sumc--; 159 } 160 else break; 161 } 162 add(s,id,mp[i][j].sumc); 163 } 164 if(mp[i][j].sumr>0){ 165 int id=mp[i][j].rid+white+colcnt; 166 for(int k=j+1;k<m;k++){ 167 if(mp[i][k].type==2){ 168 ans[i][k]=cnt; 169 add(mp[i][k].id,id,8); 170 mp[i][j].sumr--; 171 } 172 else break; 173 } 174 add(id,t,mp[i][j].sumr); 175 } 176 } 177 } 178 int temp=ISAP(); 179 // cout<<temp<<endl; 180 for(int i=0;i<n;i++){ 181 for(int j=0;j<m;j++){ 182 if(mp[i][j].type==2){ 183 printf("%d%c",e[ans[i][j]].flow+1,j==m-1?'\n':' '); 184 } 185 else printf("_%c",j==m-1?'\n':' '); 186 } 187 } 188 } 189 return 0; 190 }
终于过了,,初始化坑死人啊。。。。
记不清被初始化坑多少次了=_=||
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int inf=0x3f3f3f3f; 4 const int maxv=200010; 5 const int maxe=1000010; // 6 #define CLR(m,a) memset(m,a,sizeof(m)) 7 8 int n,m,s,t; 9 int tot; 10 struct Edge{ 11 int u,v,cap,flow; 12 int nex; 13 }e[maxe]; 14 int head[maxv]; 15 int cnt=0; 16 void init(){ 17 CLR(head,-1); 18 cnt=0; 19 } 20 void add(int u,int v,int cap) 21 { 22 e[cnt].u=u; e[cnt].v=v; 23 e[cnt].cap=cap; e[cnt].flow=0; 24 e[cnt].nex=head[u]; head[u]=cnt++; 25 26 e[cnt].u=v; e[cnt].v=u; 27 e[cnt].cap=0; e[cnt].flow=0; 28 e[cnt].nex=head[v]; head[v]=cnt++; 29 } 30 struct node{ 31 int id,cid,rid,sumc,sumr,type; 32 }mp[110][110]; 33 int ans[110][110]; //记录该点的出边,便于输出 34 35 int vis[maxv],cur[maxv],num[maxv],d[maxv],p[maxv]; 36 37 void bfs(){ 38 CLR(d,-1); 39 CLR(vis,0); 40 queue<int> q; 41 q.push(t); 42 d[t]=0; 43 vis[t]=1; 44 while(!q.empty()){ 45 int u=q.front(); 46 q.pop(); 47 for(int i=head[u];~i;i=e[i].nex){ 48 int id=i&(-2); 49 int v=e[id].u; 50 if(!vis[v]&&e[id].cap>e[id].flow){ 51 vis[v]=1; 52 q.push(v); 53 d[v]=d[u]+1; 54 } 55 } 56 } 57 } 58 int augment(){ 59 int a=inf,u=t; 60 while(u!=s){ 61 int id=p[u]; 62 a=min(a,e[id].cap-e[id].flow); 63 u=e[id].u; 64 } 65 u=t; 66 while(u!=s){ 67 int id=p[u]; 68 e[id].flow+=a; 69 e[id^1].flow-=a; 70 u=e[id].u; 71 } 72 return a; 73 } 74 int ISAP(){ 75 bfs(); 76 int flow=0; 77 CLR(num,0); 78 for(int i=0;i<tot;i++){ 79 if(d[i]!=-1) num[d[i]]++; 80 cur[i]=head[i]; 81 } 82 int u=s; 83 while(d[s]<tot) 84 { 85 if(u==t) 86 { 87 flow+=augment(); 88 u=s; 89 } 90 int ok=0; 91 for(int i=cur[u];~i;i=e[i].nex){ 92 int v=e[i].v; 93 if(e[i].cap>e[i].flow&&d[u]==d[v]+1){ 94 ok=1; 95 cur[u]=i; 96 p[v]=i; 97 u=v; 98 break; 99 } 100 } 101 if(!ok){ 102 int m=tot-1; 103 for(int i=head[u];~i;i=e[i].nex){ 104 int v=e[i].v; 105 if(e[i].cap>e[i].flow&&d[v]!=-1) m=min(m,d[v]); 106 } 107 if(--num[d[u]]==0) break; 108 num[d[u]=m+1]++; 109 cur[u]=head[u]; 110 if(u!=s) u=e[p[u]].u; 111 } 112 } 113 return flow; 114 } 115 116 int main(){ 117 while(scanf("%d%d",&n,&m)==2){ 118 init(); 119 char c[8]; 120 int rowcnt=0,colcnt=0,white=0; 121 for(int i=0;i<n;i++) 122 for(int j=0;j<m;j++){ 123 scanf("%s",c); 124 if(c[3]=='X') { 125 mp[i][j].type=0; 126 continue; 127 } 128 else if(c[3]=='.'){ 129 white++; 130 mp[i][j].type=2; 131 mp[i][j].id=white; 132 } 133 else{ 134 mp[i][j].type=1; 135 mp[i][j].sumc=0; 136 mp[i][j].sumr=0; 137 int num; 138 if(c[0]!='X'){ 139 num=(c[0]-'0')*100+(c[1]-'0')*10+c[2]-'0'; 140 colcnt++; 141 mp[i][j].cid=colcnt; 142 mp[i][j].sumc=num; 143 } 144 if(c[4]!='X'){ 145 num=(c[4]-'0')*100+(c[5]-'0')*10+c[6]-'0'; 146 rowcnt++; 147 mp[i][j].rid=rowcnt; 148 mp[i][j].sumr=num; 149 } 150 } 151 } 152 s=0;t=white+rowcnt+colcnt+1; 153 tot=t+1; 154 //编点,white<colcnt<rowcnt 155 for(int i=0;i<n;i++) 156 for(int j=0;j<m;j++){ 157 if(mp[i][j].type==1){ 158 if(mp[i][j].sumc>0){ //如果列有数字 159 int id=mp[i][j].cid+white; 160 for(int k=i+1;k<n;k++){ 161 if(mp[k][j].type==2){ 162 add(id,mp[k][j].id,8); 163 mp[i][j].sumc--; 164 } 165 else break; 166 } 167 add(s,id,mp[i][j].sumc); 168 } 169 if(mp[i][j].sumr>0){ 170 int id=mp[i][j].rid+white+colcnt; 171 for(int k=j+1;k<m;k++){ 172 if(mp[i][k].type==2){ 173 ans[i][k]=cnt; 174 add(mp[i][k].id,id,8); 175 mp[i][j].sumr--; 176 } 177 else break; 178 } 179 add(id,t,mp[i][j].sumr); 180 } 181 } 182 } 183 int temp=ISAP(); 184 for(int i=0;i<n;i++){ 185 for(int j=0;j<m;j++){ 186 if(mp[i][j].type==2){ 187 printf("%d%c",e[ans[i][j]].flow+1,j==m-1?'\n':' '); 188 } 189 else printf("_%c",j==m-1?'\n':' '); 190 } 191 } 192 } 193 return 0; 194 }
kebab
题意:n个任务,每个任务时间区间为[si,ei],工作量为ni*ti。单位时间最大工作量为m,求是否能完成任务。
和上面的hdu3572类似,区别就是这个工作可以分成ni份同时做,还有这个题的时间区间较大,先离散化,再把每个区间看成一个点。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define CLR(m,a) memset(m,a,sizeof(m)) 4 const int maxv=610; 5 const int maxe=100010; 6 const int inf=0x3f3f3f3f; 7 struct Edge{ 8 int u,v,flow,cap; 9 int nex; 10 Edge(int u=0,int v=0,int flow=0,int cap=0,int nex=0): 11 u(u),v(v),flow(flow),cap(cap),nex(nex){} 12 }e[maxe<<2]; 13 int head[maxv]; 14 int cnt=0; 15 void init(){ 16 CLR(head,-1); 17 cnt=0; 18 } 19 void add(int u,int v,int cap){ 20 e[cnt]=Edge(u,v,0,cap,head[u]); 21 head[u]=cnt++; 22 e[cnt]=Edge(v,u,0,0,head[v]); 23 head[v]=cnt++; 24 } 25 int si[maxv],ei[maxv],ti[maxv],ni[maxv]; 26 int des[maxv<<1]; 27 28 int d[maxv],num[maxv],cur[maxv],p[maxv]; 29 int vis[maxv]; 30 int s,t; 31 int N; // 32 33 void bfs(){ 34 CLR(d,-1); 35 CLR(vis,0); 36 queue<int> q; 37 q.push(t); 38 d[t]=0; 39 vis[t]=1; 40 while(!q.empty()){ 41 int u=q.front(); 42 q.pop(); 43 for(int i=head[u];~i;i=e[i].nex){ 44 int id=i&(-2); 45 int v=e[id].u; 46 if(!vis[v]&&e[id].cap>e[id].flow){ 47 vis[v]=1; 48 d[v]=d[u]+1; 49 q.push(v); 50 } 51 } 52 } 53 // 54 } 55 56 int augment(){ 57 int u=t,a=inf; 58 while(u!=s){ 59 int id=p[u]; 60 a=min(a,e[id].cap-e[id].flow); 61 u=e[id].u; 62 } 63 u=t; 64 while(u!=s){ 65 int id=p[u]; 66 e[id].flow+=a; 67 e[id^1].flow-=a; 68 u=e[id].u; 69 } 70 return a; 71 } 72 73 int ISAP(){ 74 bfs(); 75 int flow=0; 76 CLR(num,0); 77 for(int i=0;i<N;i++){ 78 cur[i]=head[i]; 79 if(~d[i]) num[d[i]]++; 80 } 81 int u=s; 82 while(d[s]<N){ 83 if(u==t){ 84 flow+=augment(); 85 u=s; 86 } 87 int ok=0; 88 for(int i=cur[u];~i;i=e[i].nex){ 89 int v=e[i].v; 90 if(d[u]==d[v]+1&&e[i].cap>e[i].flow){ 91 p[v]=i; 92 ok=1; 93 cur[u]=i; 94 u=v; 95 break; 96 } 97 } 98 if(!ok){ 99 int m=N-1; 100 for(int i=head[u];~i;i=e[i].nex){ 101 if(e[i].cap>e[i].flow&&~d[e[i].v]) m=min(m,d[e[i].v]); 102 } 103 if(--num[d[u]]==0) break; 104 num[d[u]=m+1]++; 105 cur[u]=head[u]; 106 if(u!=s) u=e[p[u]].u; 107 } 108 } 109 return flow; 110 } 111 112 int main(){ 113 int n,m; 114 while(scanf("%d%d",&n,&m)!=EOF){ 115 int sum=0; 116 int p=0; 117 init(); 118 for(int i=1;i<=n;i++){ 119 scanf("%d%d%d%d",&si[i],&ni[i],&ei[i],&ti[i]); 120 des[p++]=si[i]; 121 des[p++]=ei[i]; 122 sum+=ni[i]*ti[i]; 123 } 124 sort(des,des+p); 125 p=unique(des,des+p)-des; 126 s=0,t=n+p; 127 for(int i=1;i<=n;i++){ 128 add(s,i,ti[i]*ni[i]); 129 } 130 for(int i=1;i<p;i++){ 131 add(n+i,t,(des[i]-des[i-1])*m); 132 for(int j=1;j<=n;j++){ 133 if(si[j]<=des[i-1]&&ei[j]>=des[i]) 134 add(j,n+i,inf); 135 } 136 } 137 N=t+1; 138 int flow=ISAP(); 139 if(flow==sum) puts("Yes"); 140 else puts("No"); 141 } 142 }
Escape
题意:n个人移民到m个星球。问是否能满足所有人的需求(即有的人不去某些星球)。
n有十万,m最大10,开始直接上模板做的,果断TLE,边数达到了1e6+。
注意到m最大是10,与n差距悬殊。考虑有多少种移民方案,每个星球选或者不选,所以最多1024种
以方案为点,该方案允许的人为边,再去建图
这样建图边数降到了1e4,过了~
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define CLR(m,a) memset(m,a,sizeof(m)) 4 const int maxv=1050; 5 const int maxe=12000; 6 const int inf=0x3f3f3f3f; 7 struct Edge{ 8 int u,v,flow,cap; 9 int nex; 10 Edge(int u=0,int v=0,int flow=0,int cap=0,int nex=0): 11 u(u),v(v),flow(flow),cap(cap),nex(nex){} 12 }e[maxe<<1]; 13 int head[maxv]; 14 int cnt=0; 15 void init(){ 16 CLR(head,-1); 17 cnt=0; 18 } 19 void add(int u,int v,int cap){ 20 e[cnt]=Edge(u,v,0,cap,head[u]); 21 head[u]=cnt++; 22 e[cnt]=Edge(v,u,0,0,head[v]); 23 head[v]=cnt++; 24 } 25 int vis[maxv],p[maxv],d[maxv],num[maxv],cur[maxv]; 26 int s,t; 27 int N; 28 29 void bfs(){ 30 CLR(d,-1); 31 CLR(vis,0); 32 queue<int> q; 33 q.push(t); 34 d[t]=0; 35 vis[t]=1; 36 while(!q.empty()){ 37 int u=q.front(); 38 q.pop(); 39 for(int i=head[u];~i;i=e[i].nex){ 40 int id=i&(-2); 41 int v=e[id].u; 42 if(!vis[v]&&e[id].cap>e[id].flow){ 43 vis[v]=1; 44 d[v]=d[u]+1; 45 q.push(v); 46 } 47 } 48 } 49 } 50 int augment(){ 51 int u=t,a=inf; 52 while(u!=s){ 53 int id=p[u]; 54 a=min(a,e[id].cap-e[id].flow); 55 u=e[id].u; 56 } 57 u=t; 58 while(u!=s){ 59 int id=p[u]; 60 e[id].flow+=a; 61 e[id^1].flow-=a; 62 u=e[id].u; 63 } 64 return a; 65 } 66 int ISAP(){ 67 bfs(); 68 CLR(num,0); 69 for(int i=0;i<N;i++){ 70 cur[i]=head[i]; 71 if(~d[i]) num[d[i]]++; 72 } 73 int flow=0; 74 int u=s; 75 while(d[s]<N){ 76 if(u==t){ 77 flow+=augment(); 78 u=s; 79 } 80 int ok=0; 81 for(int i=cur[u];~i;i=e[i].nex){ 82 int v=e[i].v; 83 if(d[u]==d[v]+1&&e[i].cap>e[i].flow){ 84 ok=1; 85 p[v]=i; 86 cur[u]=i; 87 u=v; 88 break; 89 } 90 } 91 if(!ok){ 92 int m=N-1; 93 for(int i=head[u];~i;i=e[i].nex){ 94 if(e[i].cap>e[i].flow&&~d[e[i].v]) m=min(m,d[e[i].v]); 95 } 96 if(--num[d[u]]==0) break; 97 num[d[u]=m+1]++; 98 cur[u]=head[u]; 99 if(u!=s) u=e[p[u]].u; 100 } 101 } 102 return flow; 103 } 104 int val[maxv]; 105 int main(){ 106 int n,m; 107 while(scanf("%d%d",&n,&m)!=EOF){ 108 init(); 109 int x; 110 CLR(val,0); 111 for(int i=1;i<=n;i++){ 112 int temp=0; 113 for(int j=1;j<=m;j++){ 114 scanf("%d",&x); 115 temp=(temp<<1)+x; 116 } 117 val[temp]++; 118 } 119 int bc=(1<<m)-1; 120 s=0;t=bc+m+1; 121 N=t+1; 122 for(int i=1;i<=m;i++){ 123 scanf("%d",&x); 124 add(bc+i,t,x); 125 } 126 if(val[0]) { 127 puts("NO"); 128 continue; 129 } 130 for(int i=1;i<=bc;i++)if(val[i]){ 131 add(s,i,val[i]); 132 for(int j=1;j<=m;j++) if(i>>(m-j)&1){ //位运算又出了差错=_=|| 133 add(i,bc+j,inf); 134 } 135 } 136 int flow=ISAP(); 137 if(flow==n) puts("YES"); 138 else puts("NO"); 139 } 140 return 0; 141 }