题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3157
You’ve just built a circuit board for your new robot, and now you need to power it. Your robot circuit consists of a number of electrical components that each require a certain amount of current to operate. Every component has a + and a - lead, which are connected on the circuit board at junctions. Current flows through the component from + to - (but note that a component does not "use up" the current: everything that comes in through the + end goes out the - end).
The junctions on the board are labeled 1, ..., N, except for
two special junctions labeled + and - where the power supply terminals are
connected. The + terminal only connects + leads, and the - terminal only
connects - leads. All current that enters a junction from the - leads of
connected components exits through connected + leads, but you are able to
control how much current flows to each connected + lead at every junction
(though methods for doing so are beyond the scope of this problem1).
Moreover, you know you have assembled the circuit in such a way that there are
no feedback loops (components chained in a manner that allows current to flow in
a loop).
In the interest of saving power, and also to ensure that your circuit does not overheat, you would like to use as little current as possible to get your robot to work. What is the smallest amount of current that you need to put through the + terminal (which you can imagine all necessarily leaving through the - terminal) so that every component on your robot receives its required supply of current to function?
Hint
1 For
those who are electronics-inclined, imagine that you have the ability to adjust
the potential on any componentwithout altering its current requirement, or
equivalently that there is an accurate variable potentiometer connected in
series with each component that you can adjust. Your power supply will have
ample potential for the circuit.
题意:很好理解,如图中所示,求解J+到J-的最小流量。
解法:有源汇的上下界最小流。
构图方法:新增超级源点汇点,分别为from,to。对原图中任意一条边u->v(流量下界为b),保留此边,流量上界为inf-b,下界为0;from->v(cap=b);
u->to(cap=b)。
最小流:求from,to的最大流;然后连边(J-) -> (J+)(cap=inf),再次求解from,to最大流,累加两次最大流流量。若满流,则经过(J-) -> (J+)的流量就是最小流。
随便说一句,这道题的N应该不止50吧,数组开到60把我给WA了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #define inf 0x7fffffff 9 using namespace std; 10 const int maxn=600; 11 const int M = 100000+10; 12 13 struct Edge 14 { 15 int to,cap,next; 16 }edge[M*2]; 17 int head[maxn],edgenum; 18 int n,m,from,to,vnum,s,t; 19 20 void add(int u,int v,int cap) 21 { 22 edge[edgenum].to=v; 23 edge[edgenum].cap=cap; 24 edge[edgenum].next=head[u]; 25 head[u]=edgenum++; 26 27 edge[edgenum].to=u; 28 edge[edgenum].cap=0; 29 edge[edgenum].next=head[v]; 30 head[v]=edgenum++; 31 } 32 33 int level[maxn]; 34 int gap[maxn]; 35 void bfs(int to) 36 { 37 memset(level,-1,sizeof(level)); 38 memset(gap,0,sizeof(gap)); 39 level[to]=0; 40 gap[level[to] ]++; 41 queue<int> Q; 42 Q.push(to); 43 while (!Q.empty()) 44 { 45 int u=Q.front() ;Q.pop() ; 46 for (int i=head[u] ;i!=-1 ;i=edge[i].next) 47 { 48 int v=edge[i].to; 49 if (level[v] != -1) continue; 50 level[v]=level[u]+1; 51 gap[level[v] ]++; 52 Q.push(v); 53 } 54 } 55 } 56 57 int cur[maxn]; 58 int pre[maxn]; 59 int SAP(int from,int to) 60 { 61 bfs(to); 62 memset(pre,-1,sizeof(pre)); 63 memcpy(cur,head,sizeof(head)); 64 int u=pre[from]=from,flow=0,aug=inf; 65 gap[from]=vnum; 66 while (level[from]<vnum) 67 { 68 bool flag=false; 69 for (int &i=cur[u] ;i!=-1 ;i=edge[i].next) 70 { 71 int v=edge[i].to; 72 if (edge[i].cap && level[u]==level[v]+1) 73 { 74 flag=true; 75 aug=min(aug,edge[i].cap); 76 pre[v]=u; 77 u=v; 78 if (v==to) 79 { 80 flow += aug; 81 for (u=pre[u] ;v!=from ;v=u ,u=pre[u]) 82 { 83 edge[cur[u] ].cap -= aug; 84 edge[cur[u]^1 ].cap += aug; 85 } 86 aug=inf; 87 } 88 break; 89 } 90 } 91 if (flag) continue; 92 int minlevel=vnum; 93 for (int i=head[u] ;i!=-1 ;i=edge[i].next) 94 { 95 int v=edge[i].to; 96 if (edge[i].cap && level[v]<minlevel) 97 { 98 minlevel=level[v]; 99 cur[u]=i; 100 } 101 } 102 if (--gap[level[u] ]==0) break; 103 level[u]=minlevel+1; 104 gap[level[u] ]++; 105 u=pre[u]; 106 } 107 return flow; 108 } 109 110 int main() 111 { 112 while (scanf("%d%d",&n,&m)!=EOF) 113 { 114 if (!n && !m) break; 115 memset(head,-1,sizeof(head)); 116 edgenum=0; 117 char c[5],c2[5]; 118 int u,v; 119 int cap,f=M; 120 s=0 ;t=n+1 ;from=t+1 ;to=from+1 ; 121 vnum=to+1; 122 int sum=0; 123 for (int i=0 ;i<m ;i++) 124 { 125 scanf("%s%s%d",&c,&c2,&cap); 126 sum += cap; 127 if (c[0]==‘+‘) u=s; 128 else sscanf(c,"%d",&u); 129 if (c2[0]==‘-‘) v=t; 130 else sscanf(c2,"%d",&v); 131 add(u,v,f-cap); 132 add(from,v,cap); 133 add(u,to,cap); 134 //cout<<"debug"<<endl; 135 } 136 int Maxflow=SAP(from,to); 137 int d=edgenum; 138 add(t,s,inf); 139 Maxflow += SAP(from,to); 140 int flag=0; 141 for (int i=head[from] ;i!=-1 ;i=edge[i].next) 142 { 143 if (edge[i].cap) {flag=1;break; } 144 } 145 if (Maxflow==sum) printf("%d\n",edge[(d^1)].cap); 146 else printf("impossible\n"); 147 } 148 return 0; 149 }