poj 3469 Dual Core CPU(最小割)

http://poj.org/problem?id=3469


题目大意:

SWODNIW的双核cpu包含n个模块,各个肿块在每个cpu中的耗费分别为a和b;

同时m对模块之间需要徐局共享,也就是说需要共享的两个模块不在同一个cpu中运行就要花费w来用于数据共享;

求出最小耗费;


思路:

妥妥的最小割,建图也不难,建立源点s,汇点t,模块作为顶点。

s到每个模块的边容量为a,每个模块到t的容量为b,需要数据共享的模块之间的容量为w;


ps:一直用的不爱用邻接表,习惯邻接矩阵,这次看到这题傻了眼!!用的网上的模板,看来要自己准备一份邻接表的模板了


#include<iostream>
using namespace std;

const int max_n=20010;
const int max_m=200010;
const int inf=1<<26;

class Edge
{
public:
	int v;
	int next;
	int w;
}edge[8*max_m];

int head[max_n];
int edge_num;
int n,m;
int s,t;

void addedge(int u,int v,int w)
{
	edge[edge_num].v=v;
	edge[edge_num].w=w;
	edge[edge_num].next=head[u];
	head[u]=edge_num++;
	
	edge[edge_num].v=u;
	edge[edge_num].w=0;
	edge[edge_num].next=head[v];
	head[v]=edge_num++;
}

int maxflow()
{
	int pre[max_n];
	int cur[max_n];
	int dist[max_n];
	int gap[max_n];
	
	int max_flow=0;
	int min_flow=inf;
	int u,v;
	
	for(int i=0;i<=n;i++)
	{
		cur[i]=head[i];
		gap[i]=dist[i]=0;
	}

	gap[s]=n;
	u=pre[s]=s;
	
	bool flag;
	while(dist[s]<n)
	{
		flag=false;
		for(int &j=cur[u];j!=-1;j=edge[j].next)
		{
			v=edge[j].v;
			if(edge[j].w>0 && dist[u]==dist[v]+1)
			{
				flag=true;
				if(edge[j].w<min_flow)
					min_flow=edge[j].w;
				pre[v]=u;
				u=v;
				if(u==t)
				{
					max_flow += min_flow;
					while(u!=s)
					{
						u=pre[u];
						edge[ cur[u] ].w -= min_flow;
						edge[ cur[u]^1 ].w += min_flow;
					}
					min_flow=inf;
				}
				break;
			}
		}
		if(flag)
			continue;

		int min_dist=n;
		for(int k=head[u];k!=-1;k=edge[k].next)
		{
			v=edge[k].v;
			if(edge[k].w>0 && dist[v]<min_dist)
			{
				min_dist=dist[v];
				cur[u]=k;
			}
		}
		if( (--gap[ dist[u] ] )==0)
			break;
		gap[ dist[u]=min_dist+1 ]++;
		u=pre[u];
	}
	return max_flow;
}

int main(int i,int j)
{
	while(~scanf("%d %d",&n,&m))
	{
		/*Initial*/
		t=n+1;
		s=0;
		edge_num=0;
		memset(head,-1,sizeof(head));

		/*Input & Structure Graph*/
		for(i=1;i<=n;i++)
		{
			int a,b;
			scanf("%d %d",&a,&b);
			addedge(s,i,a);
			addedge(i,t,b);
		}
		for(j=0;j<m;j++)
		{
			int u,v,w;
			scanf("%d %d %d",&u,&v,&w);
			addedge(u,v,w);
			addedge(v,u,w);
		}
		n += 2;
		printf("%d\n",maxflow());
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值