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).

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 }
时间: 2024-12-28 12:48:44

hdu 3157 Crazy Circuits 网络流的相关文章

HDU 3157 Crazy Circuits(有源汇上下界最小流)

HDU 3157 Crazy Circuits 题目链接 题意:一个电路板,上面有N个接线柱(标号1~N),还有两个电源接线柱 + -,给出一些线路,每个线路有一个下限值求一个可以让所有部件正常工作的总电流 没有则输出impossible 思路: 有源汇有上下界求最小流,建模方法为: 按无源汇先建图,跑超级源汇ss->tt一次,然后加入t->s,容量INF的边,在跑一次ss->tt,如果是满流,就有解,解为t->s边的当前流量 顺带写个最大流的,最大流就先把t->s加入直接跑

POJ 3801/HDU 3157 Crazy Circuits | 有下界的最小流

题目: POJ最近总是炸 所以还是用HDU吧http://acm.hdu.edu.cn/showproblem.php?pid=3157 题解: 题很长,但其实就是给个有源汇带下界网络流(+是源,-是汇),求最小流 求法: 1.模仿可行流建图,但是不加t到s的INF边 2.跑最大流 3.加t到sINF边 4.跑最大流 5.如果两次答案相加不等于sum,无解; 6.如果有解,t到s的反边流量就是答案 #include<cstdio> #include<algorithm> #incl

[hdu] 3157 Crazy Circuits || 有源汇上下界最小流

原题 有两个正负极n个节点和m个元件,每个元件告诉端点是接在哪个节点上的,并且每个元件有工作的最小电流限制,问使所有元件工作的满足条件的最小电流是多少. 有源汇上下界最小流. 考虑dinic的推流思想,所以在跑完可行流后,减去t到s的最大流就是最小流. 实现方法: 建图时先不加入t到s的inf边,跑最大流,再加入inf边跑最大流.若此刻是可行流,那么加入的t到s的inf边的反向边的权值就是最小流. ll ans=0; ans+=dinic(); add(t,s,inf); ans+=dinic(

hdoj 3157 Crazy Circuits 【有下界最小流】

题目:hdoj 3157 Crazy Circuits 题意:现在要制造一个电路板,电路板上有 n 个电子元件,各个元件之间有单向的电流流向,然后有一个 + ,电流进入, -- 电流汇入,然后判断能不能让电路板工作,如果能的话求最小电流. 分析:有上下界网络流,求最小流 首先是判断能不能够让电路板工作,能工作的条件就是流量平衡,判断方法前面题目中讲过. 同样先转换为无源汇网络流问题,添加t→ s边权为无穷.那么最小流不就是在满足所有下界的情况的流么.即上面提到的,求得SS→ TT的最大流之后,其

HDOJ 3157 Crazy Circuits

给一些电路上的两个点和这两个点之间最少要通过的电流,要求正极到负极间的流量再满足条件的情况下最少 有源汇点上下界最小流: 建图: 设原源汇点 s,t 建立超级源汇点S,T先不连接 t-->s 像无源汇点可行流判断一样的建图,对S,T跑一遍最大流,记录流量f1... 连接源汇点 t--->s 无下界,上界INF ....再对S,T跑一遍最大流,得到流量f2... 如果  则存在最小流,最小流流量既 t--->s 的后悔边的流量. 否则无解 Crazy Circuits Time Limit

Crazy Circuits (hdu 3157 流量有上下限的最小流)

Crazy Circuits Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 611    Accepted Submission(s): 308 Problem Description You've just built a circuit board for your new robot, and now you need to p

hdu Crazy Circuits

Crazy Circuits 题目: 给出一个电路板,从+极出发到负极. 如今给你电路板上的最小电流限制,要你在电流平衡的时候求得从正极出发的最小电流. 算法: 非常裸的有源汇最小流.安有源汇最大流做法后,先求出最大流.然后.通过加入 t-->s 容量INF,是其变成一个无源汇最小流问题.这样在跑一次最大流就是结果了.尽管没有严格证明是否正确,可是我用到如今,还没发现有错误的算法. 做题时in[]忘记清空了.找了半个小时!!! /* //!!!!!!!!!!!!!! 一定要注意清空初始化问题.!

hdu 4289 Control(网络流 最大流+拆点)(模板)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4289 Control Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1545    Accepted Submission(s): 677 Problem Description You, the head of Department o

HDU 1853Cyclic Tour(网络流之最小费用流)

题目地址:HDU1853 费用流果然好神奇..还可以用来判断环...如果每个点都是环的一部分而且每个点只能用到一次的话,那每个点的初度入度都是1,这就可以利用网络流来解决,只要拆点令其流量为1,就限制了每个点只能用一次,每次左边的连到右边的,就相当于左边点的一次初度和右边的点的一次入度,很容易想象出来.最后只要判断总流量是否为n即可,因为如果总流量为n的话,说明每个点都出了一次度,每个点都入了一次度,而且由于拆点的流量限制,充分说明了每个点的初度入度都是1.进而说明了每个点都在环里.然后输出最后