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

题目:hdoj 3157 Crazy Circuits

题意:现在要制造一个电路板,电路板上有 n 个电子元件,各个元件之间有单向的电流流向,然后有一个 + ,电流进入, -- 电流汇入,然后判断能不能让电路板工作,如果能的话求最小电流。

分析:有上下界网络流,求最小流

首先是判断能不能够让电路板工作,能工作的条件就是流量平衡,判断方法前面题目中讲过。

同样先转换为无源汇网络流问题,添加t→ s边权为无穷。那么最小流不就是在满足所有下界的情况的流么。即上面提到的,求得SS→ TT的最大流之后,其后悔边s→ t的边权即为最小流。但是wa了,下面看一个wa的例子:

最后求得SS→ TT的最大流之后,得到后悔边s→ t的边权为200,实际上该网络最小流只要100:

s→ 1:100

1→ 3:200

3→ 2:200

2→ 1:100

2→ t:100

问题出在原图中存在环,循环流,而我们没有利用,导致流增大了。

解决方法:先不加t→ s边权为无穷的边,求SS→ TT的最大流,如果还没有流满则再加t→ s边权为无穷的边,再求一次最大流得到后悔边s→ t就是原问题的最小流了。

PS:

1:网络流中的边是有向的,一定要注意区别,而且有上下界网络流连超级超级源点ss和超级超级汇点 tt 建边的时候,当前点流量come - to < 0 ,即需要进入流量时,建边s----> i ,当cone - to > 0,需要出去流量时,建边  i ---> tt 。但是这个题目并不是这样,刚好相反,所以搞了很久,开始没想清楚。

#include <cstdio>
#include <cstring>
#include <string>
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#define Del(a,b) memset(a,b,sizeof(a))
using namespace std;
const int inf = 0x3f3f3f3f;
const int N = 150;
struct Node
{
    int from,to,cap,flow;
};
vector<int> v[N];
vector<Node> e;
int vis[N];  //构建层次图
int cur[N];
void add_Node(int from,int to,int cap)
{
    e.push_back((Node){from,to,cap,0});
    e.push_back((Node){to,from,0,0});
    int tmp=e.size();
    v[from].push_back(tmp-2);
    v[to].push_back(tmp-1);
}
bool bfs(int s,int t)
{
    Del(vis,-1);
    queue<int> q;
    q.push(s);
    vis[s] = 0;
    while(!q.empty())
    {
        int x=q.front();
        q.pop();
        for(int i=0;i<v[x].size();i++)
        {
            Node tmp = e[v[x][i]];
            if(vis[tmp.to]<0 && tmp.cap>tmp.flow)  //第二个条件保证
            {
                vis[tmp.to]=vis[x]+1;
                q.push(tmp.to);
            }
        }
    }
    if(vis[t]>0)
        return true;
    return false;
}
int dfs(int o,int f,int t)
{
    if(o==t || f==0)  //优化
        return f;
    int a = 0,ans=0;
    for(int &i=cur[o];i<v[o].size();i++) //注意前面 ’&‘,很重要的优化
    {
        Node &tmp = e[v[o][i]];
        if(vis[tmp.to]==(vis[o]+1) && (a = dfs(tmp.to,min(f,tmp.cap-tmp.flow),t))>0)
        {
            tmp.flow+=a;
            e[v[o][i]^1].flow-=a; //存图方式
            ans+=a;
            f-=a;
            if(f==0)  //注意优化
                break;
        }
    }
    return ans;  //优化
}
int dinci(int s,int t)
{
    int ans=0;
    while(bfs(s,t))
    {
        Del(cur,0);
        int tm=dfs(s,inf,t);
        ans+=tm;
    }
    return ans;
}
void MP_clear(int n)
{
    for(int i=0;i<=n;i++)
        v[i].clear();
    e.clear();
}
int in[N];
int solve(string s,int n,int ff)
{
    int ans[5],len=0,tmp=0;
    for(int i=0;i<s.size();i++)
    {
        if(s[i]=='+')
            ans[len++]=0,tmp=0,i++;
        else if(s[i]=='-')
            ans[len++]=n+1,tmp=0,i++;
        else if(s[i]==' ')
            ans[len++]=tmp,tmp=0;
        else
            tmp = tmp * 10 + (s[i]-'0');
    }
    ans[len++]=tmp;
    add_Node(ans[0],ans[1],inf);
    in[ans[0]]-=ans[2];
    in[ans[1]]+=ans[2];
    //printf("%d %d %d\n",ans[0],ans[1],ans[2]);
    if(ans[0]==0 && ans[1]==(n+1) || ans[1]==0 && ans[0]==(n+1)){
        ff+=ans[2];
    }
    return ff;
}
int main()
{
    //freopen("Input.txt","r",stdin);
    int n,m;
    while(~scanf("%d%d",&n,&m) && m+n)
    {
        getchar();//
        Del(in,0);
        int s=0,t=n+1,ff=0;
        for(int i=0;i<m;i++)
        {
            string s;
            getline(cin,s);
            ff=solve(s,n,ff);
        }
        int ss=t+1,tt=ss+1;
        int sum=0;
        for(int i=0;i<=t;i++)
        {
            if(in[i]>0)
                sum+=(in[i]),add_Node(ss,i,in[i]);
            if(in[i]<0)
                add_Node(i,tt,-in[i]);
        }
        int ans2=dinci(ss,tt);
        add_Node(t,s,inf);
        int ans1 = dinci(ss,tt);
        int ans=ans2+ans1;
        //printf("%d %d %d\n",ans2,ans1,sum);
        if(ans==sum)
            printf("%d\n",e[e.size()-2].flow);
        else
            puts("impossible");
        MP_clear(tt);
    }
    return 0;
}
时间: 2024-10-03 20:37:13

hdoj 3157 Crazy Circuits 【有下界最小流】的相关文章

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

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(有源汇上下界最小流)

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

[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(

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

有上下界的网络流3-有源汇带上下界最小流SGU176

题目大意:有一个类似于工业加工生产的机器,起点为1终点为n,中间生产环节有货物加工数量限制,输入u v z c, 当c等于1时表示这个加工的环节必须对纽带上的货物全部加工(即上下界都为z),c等于0表示加工上界限制为z,下界为0,求节点1(起点)最少需要投放多少货物才能传送带正常工作. 解题思路:    1.直接 增设超级源点ss和超级汇点tt并连上附加边,对 当前图 求 无源汇带上下界可行流    2.将图的汇点sd连一条容量无限制的边到图的源点st,再求一遍 无源汇带上下界可行流    3.

POJ 3801 有上下界最小流

1: /** 2: POJ 3801 有上下界的最小流 3: 4: 1.对supersrc到supersink 求一次最大流,记为f1.(在有源汇的情况下,先使整个网络趋向必须边尽量满足的情况) 5: 2.添加一条边sink -> src,流量上限为INF,这条边记为p.(构造无源汇网络) 6: 3.对supersrc到supersink再次求最大流,记为f2,这里判断是否为可行流.(要判断可行,必须先构造无源汇网络流,因此要再次求最大流) 7: 8: 此网络流的最小流即为 sink -> s

sgu 176 Flow construction(有源汇的上下界最小流)

[题目链接] http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11025 [模型] 有源汇点的上下界最小流.即既满足上下界又满足流量平衡的最小流量. [思路] 按照可行流构造网络.不连t->s的边先跑一遍附加源汇点的最大流,然后连t->s一条inf边,在残量网络上跑一遍最大流.第一次求最大流所以能走的边都已经流满,第二次求附加源汇点最大流t->s的流量就会尽可能小. 另外还可以二分下界mid,然后连边(T,S,mid

【bzoj2150】部落战争 有上下界最小流

题目描述 lanzerb的部落在A国的上部,他们不满天寒地冻的环境,于是准备向A国的下部征战来获得更大的领土. A国是一个M*N的矩阵,其中某些地方是城镇,某些地方是高山深涧无人居住.lanzerb把自己的部落分成若干支军队,他们约定: 1. 每支军队可以从任意一个城镇出发,并只能从上往向下征战,不能回头.途中只能经过城镇,不能经过高山深涧. 2. 如果某个城镇被某支军队到过,则其他军队不能再去那个城镇了. 3. 每支军队都可以在任意一个城镇停止征战. 4. 所有军队都很奇怪,他们走的方法有点像