• poj 3469


    哎,被这道题搞死啦,详细解释在代码中

    //最小割模型。首先建网络流模型,建立源点s和终点t(分别代表这两块不同的芯片),然后把s和每个点之间连一条容量为1,方向从s到点的边(方向
    //一定要确定,因为割的容量的定义),然后从每个点到终点连一条容量为1,方向为点到t的边,然后在有联系的
    //两点之间建一条容量为1的无向边(即一对容量为1方向相反的有向边)。建图完成。那么,在这个网络流模型中的一个割
    //就对应于一种选择方案,而此方案的花费即割的容量。原因如下:先看所有的点都没有联系的情况,那么所有点和s的边
    //和t的边这两条边有且仅有一条边在割去的边的集合中,哪条边割去说明点在哪个芯片上,那么割的容量就等于总花费(根
    //据我们所建的模型)。说明一个割就是一种方案。然后考虑有有联系的点。对于一对有联系的点如果选择了同一块芯片,那么
    //他们之间的那对相反方向的边就不在割去的边的集合中,所以此时总的花费也是等于割的容量。如果选择了不同的芯片,那么
    //他们之间的边就在割去的边的集合中,此时总的花费也等于个的容量。注意此时,那对双向边的容量并没有造成花费的重复计算
    //因为割的容量只是所有从s到t的边的容量值和,那两条双向边中只有一条是算在容量中,这也是为什么连接双向而不是单项边的
    //原因,因为单向边会造成割的容量小于实际花费,两个点之间的花费没有算在割的容量中。所以此题求最小花费就是求最小割的容量,
    //也即最大流的大小。数据量很大,用的是Dinic
    	#include <iostream>
    	#include <cstring>
    	#include <cstdio>
    	#include <queue>
    	using namespace std;
    	const int maxn=20003;
    	const int maxe=900000;
    	const int inf=1<<25;
    	struct Edge
    	{
    		int from,to,next;
    	};
    	Edge edges[maxe];
    	int p[maxn],num[maxn],flow[maxe],cap[maxe],d[maxn],cur[maxn],head[maxn]; 
    	int n,m,tot,s,t;
    	bool bfs()
    	{
    		memset(d,-1,sizeof(d));
    		queue<int> q;
    		q.push(s);
    		d[s]=0;
    		while(!q.empty())
    		{
    			int x=q.front();q.pop();
    			for(int i=head[x];i!=-1;i=edges[i].next)
    			{
    				Edge& e=edges[i];
    				if(d[e.to]==-1&&cap[i]>flow[i])
    				{
    					d[e.to]=d[x]+1;
    					q.push(e.to);
    				}
    			}
    		}
    		if(d[t]!=-1) return true;
    		else return false;
    	}
    	int dfs(int x,int a)
    	{
    		if(x==t||a==0) return a;
    		int tflow=0,f;
    		for(int i=cur[x];i!=-1;i=edges[i].next)
    		{
    			Edge& e=edges[i];
    			if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,cap[i]-flow[i])))>0)
    			{
    				flow[i]+=f;
    				flow[i^1]-=f;
    				tflow+=f;
    				a-=f;
    				if(a==0) break;
    			}
    		}
    		return tflow;
    	}
    	int maxflow()
    	{
    		int tflow=0;
    		while(bfs())
    		{
    			memcpy(cur,head,(n+2)*sizeof(int));
    			tflow+=dfs(s,inf);
    		}
    		return tflow;
    	}
    	void addedge(int from,int to,int ecap)
    	{
    		edges[tot].from=from;
    		edges[tot].to=to;
    		cap[tot]=ecap;
    		edges[tot].next=head[from];
    		head[from]=tot;
    		tot++;
    		edges[tot].from=to;
    		edges[tot].to=from;
    		cap[tot]=0;
    		edges[tot].next=head[to];
    		head[to]=tot;
    		tot++;
    	}
    	void init()
    	{
    		tot=0;
    		memset(flow,0,sizeof(flow));
    		memset(cap,0,sizeof(cap));
    		memset(head,-1,sizeof(head));
    	}
    	int main()
    	{
    		while(scanf("%d%d",&n,&m)!=EOF)
    		{
    			s=0;t=n+1;
    			int i,j,ga,gb,a,b,w;
    			init();
    			for(i=1;i<=n;i++)
    			{
    				scanf("%d%d",&ga,&gb);
    				addedge(0,i,ga);
    				addedge(i,n+1,gb);
    			}
    			for(i=1;i<=m;i++)
    			{
    				scanf("%d%d%d",&a,&b,&w);
    				addedge(a,b,w);
    				addedge(b,a,w);
    			}
    			printf("%d\n",maxflow());
    		}
    		return 0;
    	}
    		
    


  • 相关阅读:
    Vue 左右翻页,点赞动画
    gitbook 使用
    css3 序列帧动画抖动
    ios添加-webkit-overflow-scrolling依然卡顿
    css 多行省略号兼容移动端
    Vue粒子特效(vue-particles插件)
    css3 渐变色兼容移动端
    前端性能优化:客户端从输入到展示讲解
    前端通信:ajax设计方案(六)--- 全局配置、请求格式拓展和优化、请求二进制类型、浏览器错误搜集以及npm打包发布
    前端通信:ajax设计方案(五)--- 集成promise规范,更优雅的书写代码(改迭代已作废,移步迭代10)
  • 原文地址:https://www.cnblogs.com/lj030/p/3002338.html
Copyright © 2020-2023  润新知