poj 3469

       这道题是用解决最大流问题的Dinic算法写的,由于题目数据量较大,所以要选择较为高效的算法。

       这道题应该算一种经典的题型,用最小费用将对象分成两个集合的问题,利用最大流最小割定理来解决。通过构图,使得最小费用等于最小割的容量,从而通过最大流算法求出最小割的容量,也即为最小的费用。

       就这道题而言,N个模块作为N个点,与源点有容量为B的弧,与汇点有容量为A的弧,如果a,b两点在不同的CPU核上工作有额外的费用,则在从a连一条容量为w指向b的弧,连一条同样容量由b到a的弧。构好图,接下来就是求最大流最小割的问题。

代码(C++):

#include <cstdlib>
#include <iostream>
#include <queue>
#include <algorithm>

#define MAX 20050
#define INF (1<<30)
using namespace std;

//#define LOCAL

struct Edge{
    int v;
    int cap;
    int next;   
} edge[MAX*10*2*2+MAX*4];

int head[MAX],c,level[MAX];

void add_edge(int u,int v,int cap)
{
    edge[c].v=v;
    edge[c].cap=cap;
    edge[c].next=head[u];
    head[u]=c;
    c++;
    
    edge[c].v=u;
    edge[c].cap=0;
    edge[c].next=head[v];
    head[v]=c;
    c++; 
}

void bfs(int s)
{
     int u,v,i;
     queue<int> qi;
     
     level[s]=0;
     qi.push(s);
     while(!qi.empty())
     {
         u=qi.front();
         qi.pop();
         for(i=head[u];i!=-1;i=edge[i].next)
         {
             v=edge[i].v;                          
             if(edge[i].cap>0&&level[v]==-1)
             {               
                 level[v]=level[u]+1;
                 qi.push(v);             
             }                              
         }              
     }
}

int dfs(int u,int t,int f)
{
    int i,v,d,res;
    if(u==t) return f;
    res=0;
    for(i=head[u];i!=-1;i=edge[i].next)
    {
         v=edge[i].v;                              
         if(edge[i].cap>0&&level[v]==level[u]+1) 
         {
             d=dfs(v,t,min(edge[i].cap,f-res));  
             if(d>0)
             {
                edge[i].cap-=d;
                edge[i^1].cap+=d; 
                res+=d;
                if(res==f) return res;   
             }               
         }                             
    }
    return res;
}

int dinic(int s,int t)
{
    int flow;
    flow=0;
    while(1)
    {
        memset(level,-1,sizeof(level));
        bfs(s);
        if(level[t]==-1) return flow;
        flow+=dfs(s,t,INF); 
    }
}

int main(int argc, char *argv[])
{
#ifdef LOCAL
   freopen("in.txt","r",stdin);
   freopen("out.txt","w",stdout);
#endif
    int n,m,a,b,w,i;
    while(scanf("%d %d",&n,&m)!=EOF)//超级源点:0    超级汇点:n+1    模块:1~n 
    {
        c=0;            
        memset(head,-1,sizeof(head));            
        for(i=1;i<=n;i++)
        {
             scanf("%d %d",&a,&b);
             add_edge(0,i,b);
             add_edge(i,n+1,a);             
        } 
        for(i=0;i<m;i++)
        {
            scanf("%d %d %d",&a,&b,&w);
            add_edge(a,b,w);
            add_edge(b,a,w);            
        }  
        printf("%d\n",dinic(0,n+1));         
    }
    system("PAUSE");
    return EXIT_SUCCESS;
}

题目( http://poj.org/problem?id=3469):

Dual Core CPU
Time Limit: 15000MS Memory Limit: 131072K
   
Case Time Limit: 5000MS

Description

As more and more computers are equipped with dual core CPU, SetagLilb, the Chief Technology Officer of TinySoft Corporation, decided to update their famous product - SWODNIW.

The routine consists of N modules, and each of them should run in a certain core. The costs for all the routines to execute on two cores has been estimated. Let's define them as Ai and Bi. Meanwhile, M pairs of modules need to do some data-exchange. If they are running on the same core, then the cost of this action can be ignored. Otherwise, some extra cost are needed. You should arrange wisely to minimize the total cost.


Input

There are two integers in the first line of input data, N and M (1 ≤ N ≤ 20000, 1 ≤ M ≤ 200000) .
The next N lines, each contains two integer, Ai and Bi.
In the following M lines, each contains three integers: abw. The meaning is that if module a and module b don't execute on the same core, you should pay extra w dollars for the data-exchange between them.


Output

Output only one integer, the minimum total cost.


Sample Input

3 1
1 10
2 10
10 3
2 3 1000


Sample Output

13

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值