专题链接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=68128#overview
网络流基础知识:http://www.cnblogs.com/yaoyueduzhen/p/5020722.html
本专题考察网络流问题, 包含最大流和最小费用最大流,请使用高效模板。
A. poj3436 ACM Computer Factory
分析:这个是一个网络流,对流过每个点的流量有限制,这样就需要拆点,把每个结点拆成两个,一个入点,一个出点,并从入点到出点连接一条边流量为点的的流向限制,把所有接入该点的边接入它的入点,从该点流出的边从出点流出。
建图方法,每个机器是一个点,把源与所有没有必须元件的点连接,所有完整元件的点与汇连接,若一台机器的输出能符合另一台机器的输入条件则连一条边。把每个机器拆点,其内部边流量为其生产速度。
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 6 using namespace std; 7 const int MAXN=120; 8 const int MAXM=120*120; 9 const int INF=0x3f3f3f3f; 10 int p,n; 11 int q[MAXN]; 12 int in[MAXN][MAXN],out[MAXN][MAXN]; 13 14 struct Edge 15 { 16 int to, next, cap, flow; 17 }edge[MAXM]; 18 int tol; 19 int head[MAXN]; 20 void init() 21 { 22 tol = 2; 23 memset(head, -1, sizeof(head)); 24 } 25 void addedge(int u, int v, int w, int rw=0) 26 { 27 edge[tol].to = v; edge[tol].cap = w; edge[tol].flow = 0; 28 edge[tol].next = head[u]; head[u] = tol++; 29 edge[tol].to = u; edge[tol].cap = rw; edge[tol].flow = 0; 30 edge[tol].next = head[v]; head[v] = tol++; 31 } 32 int Q[MAXN]; 33 int dep[MAXN], cur[MAXN], sta[MAXN]; 34 bool bfs(int s, int t, int n) 35 { 36 int front = 0, tail = 0; 37 memset(dep, -1, sizeof(dep)); 38 dep[s] = 0; 39 Q[tail++] = s; 40 while(front < tail) 41 { 42 int u = Q[front++]; 43 for(int i = head[u]; i != -1; i = edge[i].next) 44 { 45 int v = edge[i].to; 46 if(edge[i].cap > edge[i].flow && dep[v] == -1) 47 { 48 dep[v] = dep[u] + 1; 49 if(v == t) return true; 50 Q[tail++] = v; 51 } 52 } 53 } 54 return false; 55 } 56 57 int dinic(int s, int t, int n) 58 { 59 int maxflow = 0; 60 while(bfs(s, t, n)) 61 { 62 for(int i = 0; i < n; i++) cur[i] = head[i]; 63 int u = s, tail = 0; 64 while(cur[s] != -1) 65 { 66 if(u == t) 67 { 68 int tp = INF; 69 for(int i = tail-1; i >= 0; i--) 70 tp = min(tp, edge[sta[i]].cap-edge[sta[i]].flow); 71 maxflow+=tp; 72 for(int i = tail-1; i >= 0; i--) 73 { 74 edge[sta[i]].flow+=tp; 75 edge[sta[i]^1].flow-=tp; 76 if(edge[sta[i]].cap-edge[sta[i]].flow==0) 77 tail = i; 78 } 79 u = edge[sta[tail]^1].to; 80 } 81 else 82 if(cur[u] != -1 && edge[cur[u]].cap > edge[cur[u]].flow && dep[u] + 1 == dep[edge[cur[u]].to]) 83 { 84 sta[tail++] = cur[u]; 85 u = edge[cur[u]].to; 86 } 87 else 88 { 89 while(u != s && cur[u] == -1) 90 u = edge[sta[--tail]^1].to; 91 cur[u] = edge[cur[u]].next; 92 } 93 } 94 } 95 return maxflow; 96 } 97 98 int main() 99 { 100 scanf("%d%d",&p,&n); 101 init(); 102 for(int i=1;i<=n;++i) 103 { 104 scanf("%d",&q[i]); 105 for(int j=1;j<=p;++j) 106 scanf("%d",&in[i][j]); 107 for(int j=1;j<=p;++j) 108 scanf("%d",&out[i][j]); 109 } 110 for(int i=1;i<=n;++i) 111 addedge(i,n+i,q[i]); 112 for(int i=1;i<=n;++i) 113 for(int j=1;j<=n;++j) 114 if(i!=j) 115 { 116 bool flag=true; 117 for(int k=1;k<=p;++k) 118 { 119 if(out[i][k]==0&&in[j][k]==1) 120 { 121 flag=false; 122 break; 123 } 124 if(out[i][k]==1&&in[j][k]==0) 125 { 126 flag=false; 127 break; 128 } 129 } 130 if(flag) 131 addedge(i+n,j,min(q[i],q[j])); 132 } 133 for(int i=1;i<=n;++i) 134 { 135 bool f=true; 136 for(int j=1;j<=p;++j) 137 { 138 if(in[i][j]==1) 139 { 140 f=false; 141 break; 142 } 143 } 144 if(f) addedge(0,i,q[i]); 145 } 146 for(int i=1;i<=n;++i) 147 { 148 bool f=true; 149 for(int j=1;j<=p;++j) 150 { 151 if(out[i][j]==0) 152 { 153 f=false; 154 break; 155 } 156 } 157 if(f) 158 addedge(i+n,2*n+1,q[i]); 159 } 160 int res=dinic(0,2*n+1,2*n+2); 161 int count=0; 162 for(int i=1;i<=n;++i) 163 for(int j=head[i+n];j!=-1;j=edge[j].next) 164 if(edge[j].to!=2*n+1&&edge[j].flow>0) 165 count++; 166 cout<<res<<" "<<count<<endl; 167 for(int i=1;i<=n;++i) 168 for(int j=head[i+n];j!=-1;j=edge[j].next) 169 if(edge[j].to!=2*n+1&&edge[j].flow>0) 170 cout<<i<<" "<<edge[j].to<<" "<<edge[j].flow<<endl; 171 return 0; 172 }