poj 3459 Dual Core CPU(最小割 di…

现在做题 越做心越虚了。。。 poj <wbr>3459 <wbr>Dual <wbr>Core <wbr>CPU(最小割 <wbr>dinic) 不能真正理解模版每一句的含意 根本就无法谈优化 都是加人的。我只是站在别人的肩膀上而已

题意:现在有n个任务,两个机器A和B,每个任务要么在A上完成,要么在B上完成,而且知道每个任务在A和B机器上完成所需要的费用。然后再给m行,每行 a,b,w三个数字。表示如果a任务和b任务不在同一个机器上工作的话,需要额外花费w。现在要求出完成所有任务最小的花费是多少。

思路:本来是想用stoer_wagner 做的 但。。。我不懂如何让它求出源点,和汇点分开的两个割集
所以改用dinic 求最大流 都是模版的力量,我也没什么好说的

8064K      3079MS

#include <stdio.h>
#include <string.h>
#define VM 20005
#define EM 500000
#define inf 0x3f3f3f3f
struct E
{
      int frm,to,cap,next;
}edge[EM];
int head[VM],dep[VM],p = 0;
int src,des;
void addedge (int cu,int cv,int cw,int rw)  //无向边的逆边 cap = cw,有向边的cap = 0;
{
      edge[p].frm = cu;
      edge[p].to = cv;
      edge[p].cap = cw;
      edge[p].next = head[cu];
      head[cu] = p ++;
      edge[p].frm = cv;
      edge[p].to = cu;
      edge[p].cap = rw;
      edge[p].next = head[cv];
      head[cv] = p ++;
}

int BFS ()
{
      int que[VM],i,front = 0,rear = 0;
      memset (dep,-1,sizeof(dep));
      que[rear++] = src;
      dep[src] = 0;
      while (front != rear)
      {
              int u = que[front++];
              front = front % VM;
              for (i = head[u];i != -1;i = edge[i].next)
              {
                      int v = edge[i].to;
                      if (edge[i].cap > 0&&dep[v] == -1)
                      {
                              dep[v] = dep[u] + 1;
                              que[rear++] = v;
                              rear = rear%VM;
                              if (v == des)
                                      return 1;
                      }
              }
      }
      return 0;
}

int dinic ()
{
      int i,top,res = 0;
      int stack[VM],cur[VM];
      while (BFS())
      {
              memcpy(cur,head,sizeof(head));
              int u = src;
              top = 0;
              while (1)
              {
                      if (u == des)
                      {
                              int min = inf,loc;
                              for (i = 0;i != top;i ++)
                                      if (min > edge[stack[i]].cap)
                                      {
                                              min = edge[stack[i]].cap;
                                              loc = i;
                                      }
                              for (i = 0;i != top;i ++)
                              {
                                      edge[stack[i]].cap -= min;
                                      edge[stack[i]^1].cap += min;
                              }
                              res += min;
                              top = loc;
                              u = edge[stack[top]].frm;
                      }
                      for (i = cur[u];i != -1;cur[u] = i = edge[i].next)
                              if (edge[i].cap != 0 &&dep[u] + 1 == dep[edge[i].to])
                                      break;
                      if (cur[u] != -1)
                      {
                              stack[top ++] = cur[u];
                              u = edge[cur[u]].to;
                      }
                      else
                      {
                              if (top == 0)
                                      break;
                              dep[u] = -1;
                              u = edge[stack[--top]].frm;
                      }
              }
      }
      return res;
}
int main ()
{
      int n,m,u,v,w,a,b;
      memset (head,-1,sizeof(head));
      scanf ("%d%d",&n,&m);
      src = 0;
      des = n + 1;
      for (int i = 1;i <= n;i ++)
      {
              scanf ("%d%d",&a,&b);
              addedge(src,i,a,0);
              addedge(i,des,b,0);
      }
      while (m --)
      {
              scanf ("%d%d%d",&u,&v,&w);
              addedge(u,v,w,w);
      }
      printf ("%d\n",dinic());
      return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值