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

Figure 1: Examples of two valid circuit diagrams.

In (a), all components can be powered along directed paths from the positive terminal to the negative terminal.

In (b), components 4 and 6 cannot be powered, since there is no directed path from junction 4 to the negative terminal.

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.

Input

The input file will contain multiple test cases. Each test case begins with a single line containing two integers: N (0 <= N <= 50), the number of junctions not including the positive and negative terminals, and M (1
<= M <= 200), the number of components in the circuit diagram. The next M lines each contain a description of some component in the diagram. The ith component description contains three fields: pi,
the positive junction to which the component is connected, ni, the negative junction to which the component is connected, and an integer Ii (1 <= Ii <= 100), the minimum amount
of current required for component i to function. The junctions pi and ni are specified as either the character ‘+‘ indicating the positive terminal, the character ‘-‘ indicating the negative
terminal, or an integer (between 1 and N) indicating one of the numbered junctions. No two components have the same positive junction and the same negative junction. The end-of-file is denoted by an invalid test case with N =M =
0 and should not be processed.

Output

For each input test case, your program should print out either a single integer indicating the minimum amount of current that must be supplied at the positive terminal in order to ensure that every component is powered, or the message "impossible"
if there is no way to direct a sufficient amount of current to each component simultaneously.

Sample Input

6 10
+ 1 1
1 2 1
1 3 2
2 4 5
+ - 1
4 3 2
3 5 5
4 6 2
5 - 1
6 5 3
4 6
+ 1 8
1 2 4
1 3 5
2 4 6
3 - 1
3 4 3
0 0

Sample Output

9
impossible

Source

2008 ACM-ICPC Pacific Northwest Region

Recommend

chenrui   |   We have carefully selected several similar problems for you:  3155 3154 3151 3156 3158

题意:有两个正负极n个节点和m个元件,每个元件告诉端点是接在哪个节点上的,并且每个元件有工作的最小电流限制,问使所有元件工作的满足条件的最小电流是多少。

思路:题目中已经有了源点S和汇点T,再添加附加源点SS和汇点TT,原图中的边的容量为INF(因为没有上限),若in[i]>0则SS向i连边容量为in[i],若in[i]<0则i向TT连边容量为-in[i],跑一次最大流,然后T向S连容量为INF的边,再跑一次最大流,判断SS的出边是否满流,若不满流则无解,否则有解输出边(T,S)的流量。

另外这类题看这里详解:点击打开链接

代码:

#include <iostream>
#include <functional>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

#define INF 0x3f3f3f3f
#define mod 1000000009
const int maxn = 1005;
const int MAXN = 2005;
const int MAXM = 200010;

struct Edge
{
    int to,next,cap,flow;
}edge[MAXM];

int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];

int n,m;
char s1[10],s2[10];
int in[MAXN];
int S,T,SS,TT;

void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
    memset(in,0,sizeof(in));
}

//加边,单向图三个参数,双向图四个参数
void addedge(int u,int v,int w,int rw=0)
{
    edge[tol].to=v; edge[tol].cap=w; edge[tol].next=head[u];
    edge[tol].flow=0; head[u]=tol++;
    edge[tol].to=u; edge[tol].cap=rw; edge[tol].next=head[v];
    edge[tol].flow=0; head[v]=tol++;
}

//输入参数:起点,终点,点的总数
//点的编号没有影响,只要输入点的总数
int sap(int start,int end,int N)
{
    memset(gap,0,sizeof(gap));
    memset(dep,0,sizeof(dep));
    memcpy(cur,head,sizeof(head));
    int u=start;
    pre[u]=-1;
    gap[0]=N;
    int ans=0;
    while (dep[start]<N)
    {
        if (u==end)
        {
            int Min=INF;
            for (int i=pre[u];i!=-1;i=pre[edge[i^1].to])
                if (Min>edge[i].cap-edge[i].flow)
                    Min=edge[i].cap-edge[i].flow;
            for (int i=pre[u];i!=-1;i=pre[edge[i^1].to])
            {
                edge[i].flow+=Min;
                edge[i^1].flow-=Min;
            }
            u=start;
            ans+=Min;
            continue;
        }
        bool flag=false;
        int v;
        for (int i=cur[u];i!=-1;i=edge[i].next)
        {
            v=edge[i].to;
            if (edge[i].cap-edge[i].flow && dep[v]+1==dep[u])
            {
                flag=true;
                cur[u]=pre[v]=i;
                break;
            }
        }
        if (flag)
        {
            u=v;
            continue;
        }
        int Min=N;
        for (int i=head[u];i!=-1;i=edge[i].next)
            if (edge[i].cap-edge[i].flow && dep[edge[i].to]<Min)
            {
                Min=dep[edge[i].to];
                cur[u]=i;
            }
        gap[dep[u]]--;
        if (!gap[dep[u]]) return ans;
        dep[u]=Min+1;
        gap[dep[u]]++;
        if (u!=start) u=edge[pre[u]^1].to;
    }
    return ans;
}

void solve()
{
    for (int i=0;i<=n+1;i++)
    {
        if (in[i]>0) addedge(SS,i,in[i]);
        if (in[i]<0) addedge(i,TT,-in[i]);
    }
    sap(SS,TT,n+4);
    addedge(T,S,INF);
    sap(SS,TT,n+4);
    for (int i=head[SS];~i;i=edge[i].next)
        if (edge[i].cap-edge[i].flow>0)
    {
        printf("impossible\n");
        return ;
    }
    printf("%d\n",edge[head[T]].flow);
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("C:/Users/lyf/Desktop/IN.txt","r",stdin);
#endif
    int i,j,u,v,w;
    while (scanf("%d%d",&n,&m)&&(n+m))
    {
        init();
        S=0,T=n+1,SS=n+2,TT=n+3;
        for (i=0;i<m;i++)
        {
            scanf("%s%s%d",s1,s2,&w);
            if (s1[0]=='+') u=S;
            else
            {
                u=0;
                for (j=0;j<strlen(s1);j++)
                    u=u*10+s1[j]-'0';
            }
            if (s2[0]=='-') v=T;
            else
            {
                v=0;
                for (j=0;j<strlen(s2);j++)
                    v=v*10+s2[j]-'0';
            }
            in[v]+=w;
            in[u]-=w;
            addedge(u,v,INF);
        }
        solve();
    }
    return 0;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-29 17:22:03

Crazy Circuits (hdu 3157 流量有上下限的最小流)的相关文章

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

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

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

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

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

hdu Crazy Circuits

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

River Problem (hdu 3947 流量等式建图 难题 最小费用最大流)

River Problem Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 515    Accepted Submission(s): 209 Problem Description The River of Bitland is now heavily polluted. To solve this problem, the Kin

HDU3157 Crazy Circuits

传送门 有源汇的上下界网络流求最小流. 这个其实和上道题差不多--题目描述我没怎么看明白--好像就是让你按照他说的把图建出来就行了,注意这个题的字符处理,可能有长度大于1的字符串,要注意一下.求最小流的话还是先求可行流,之后因为可行流可能流多,而从汇点向原点跑相当于退流.所以我们再从原点向汇点跑一次最大流,两次结果相减就是答案. 然后这个题其实挺奇怪的--辅助源汇点连接的边其实删不删无所谓,HDU的数据不知道行不行--然而POJ这题没数据,交个空程序就能过-- 看一下代码. #include<c

HDU 4888 Redraw Beautiful Drawings(最大流+判最大流网络是否唯一)

Problem Description Alice and Bob are playing together. Alice is crazy about art and she has visited many museums around the world. She has a good memory and she can remember all drawings she has seen. Today Alice designs a game using these drawings