HDU3157 Crazy Circuits

传送门

有源汇的上下界网络流求最小流。

这个其实和上道题差不多……题目描述我没怎么看明白……好像就是让你按照他说的把图建出来就行了,注意这个题的字符处理,可能有长度大于1的字符串,要注意一下。求最小流的话还是先求可行流,之后因为可行流可能流多,而从汇点向原点跑相当于退流。所以我们再从原点向汇点跑一次最大流,两次结果相减就是答案。

然后这个题其实挺奇怪的……辅助源汇点连接的边其实删不删无所谓,HDU的数据不知道行不行……然而POJ这题没数据,交个空程序就能过……

看一下代码。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<vector>
#include<map>
#include<queue>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar(‘\n‘)
#define fr friend inline
#define y1 poj
#define mp make_pair
#define pr pair<int,int>
#define fi first
#define sc second
#define pb push_back

using namespace std;
typedef long long ll;
const int M = 40005;
const int N = 100005;
const int INF = 0x3f3f3f3f;
const double eps = 1e-7;

int read()
{
    int ans = 0,op = 1;char ch = getchar();
    while(ch < ‘0‘ || ch > ‘9‘) {if(ch == ‘-‘) op = -1;ch = getchar();}
    while(ch >= ‘0‘ && ch <= ‘9‘) ans = ans * 10 + ch - ‘0‘,ch = getchar();
    return ans * op;
}

struct edge
{
   int next,to,from,v;
}e[N<<3];

int head[N],cur[N],deg[N],x,y,z,n,m,g,ecnt,S,T,S1,T1,c,d,tot;
int low[2005][2005],dep[N],sta[N],top;
queue <int> q;
char s[3];

void add(int x,int y,int z)
{
   e[++ecnt].to = y;
   e[ecnt].next = head[x];
   e[ecnt].v = z;
   head[x] = ecnt;
}

void clear()
{
   memset(head,-1,sizeof(head)),ecnt = -1,tot = 0;
   memset(deg,0,sizeof(deg));
}

bool bfs(int s,int t)
{
   while(!q.empty()) q.pop();
   rep(i,0,t) cur[i] = head[i];
   memset(dep,-1,sizeof(dep));
   dep[s] = 0,q.push(s);
   while(!q.empty())
   {
      int k = q.front();q.pop();
      for(int i = head[k];~i;i = e[i].next)
      {
     if(e[i].v && dep[e[i].to] == -1)
        dep[e[i].to] = dep[k] + 1,q.push(e[i].to);
      }
   }
   return dep[t] != -1;
}

int dfs(int s,int t,int lim)
{
   if(s == t || !lim) return lim;
   int flow = 0;
   for(int i = cur[s];~i;i = e[i].next)
   {
      cur[s] = i;
      if(dep[e[i].to] != dep[s] + 1) continue;
      int f = dfs(e[i].to,t,min(lim,e[i].v));
      if(f)
      {
     e[i].v -= f,e[i^1].v += f;
     flow += f,lim -= f;
     if(!lim) break;
      }
   }
   if(!flow) dep[s] = -1;
   return flow;
}

int dinic(int s,int t)
{
   int maxflow = 0;
   while(bfs(s,t)) maxflow += dfs(s,t,INF);
   return maxflow;
}

int change(char *c)
{
   if(c[0] == ‘+‘) return S;
   if(c[0] == ‘-‘) return T;
   int l = strlen(c),cur = 0;
   rep(i,0,l-1) cur *= 10,cur += c[i] - ‘0‘;
   return cur;
}     

void rebuild()
{
   e[ecnt].v = e[ecnt-1].v = 0;
   //for(int i = head[S1];~i;i = e[i].next) e[i].v = e[i^1].v = 0;
   //for(int i = head[T1];~i;i = e[i].next) e[i].v = e[i^1].v = 0;
}

int main()
{
   //freopen("f.in","r",stdin);
   //freopen("f.out","w",stdout);
   while(scanf("%d%d",&n,&m))
   {
      if(!n && !m) break;
      T = n + 1,S1 = T + 1,T1 = S1 + 1;
      clear();
      rep(i,1,m)
      {
     scanf("%s",s),x = change(s);
     scanf("%s",s),y = change(s);
     z = read(),add(x,y,INF-z),add(y,x,0),deg[x] += z,deg[y] -= z;
      }
      rep(i,S,T)
      {
     if(deg[i] > 0) add(i,T1,deg[i]),add(T1,i,0),tot += deg[i];
     else add(S1,i,-deg[i]),add(i,S1,0);
      }
      add(T,S,INF),add(S,T,0);
      int g = dinic(S1,T1);
      if(g != tot) {printf("impossible\n");continue;}
      g = e[ecnt].v,rebuild();
      printf("%d\n",g - dinic(T,S));
   }
   return 0;
}

原文地址:https://www.cnblogs.com/captain1/p/10134839.html

时间: 2024-08-30 15:28:24

HDU3157 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加入直接跑

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[]忘记清空了.找了半个小时!!! /* //!!!!!!!!!!!!!! 一定要注意清空初始化问题.!

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

【 POJ - 3801】Crazy Circuits

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 −

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

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

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