hdu 3157 Crazy Circuits 网络流

题目链接: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).
hdu 3157 Crazy Circuits 网络流_第1张图片

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 }

 

你可能感兴趣的:(HDU)