题目描述:
由于越来越多的计算机配置了双核CPU,TinySoft 公司的首席技术官员,SetagLilb,决定升级他们的产品-SWODNIW。SWODNIW 包含了N 个模块,每个模块必须运行在某个CPU 中。每个模块在每个CPU 中运行的耗费已经被估算出来了,设为Ai 和Bi。同时,M 对模块之间需要共享数据,如果他们运行在同一个CPU 中,共享数据的耗费可以忽略不计,否则,还需要额外的费用。你必须很好地安排这N 个模块,使得总耗费最小。
输入描述:
测试数据的第1 行为两个整数N 和M,1≤N≤20000,1≤M≤200000。接下来有N 行,每行为两个整数Ai 和Bi。接下来有M 行,每行为3 个整数a, b, w,表示a 模块和b 模块如果不是在同一个CPU 中运行,则需要花费额外的w 耗费来共享数据。
输出描述:输出一个整数,为最小耗费。
样例输入:
3 1
1 10
2 10
10 3
2 3 1000
样例输出:
13
这题有点神了,Dinic算法TLE了好多发啊!!!Dinic这T得无语了!后面实在不行看别人博客了!原来Dinic还有多路增广这做法,太神了!!!
就是在dfs的时候多路增广……好神……做为网络流更快的模板了……再学习下sap优化就差不多了……
这题还有点其实就是构图刚开始的时候我是有向图的,然后做着做着得有反向边啊,然后想了想,原来就是无向图而已……有向边加上其反向边就是一个强连通了,那么相当于没有方向一样了……
#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <cmath>
#include <deque>
#include <vector>
#include <list>
#include <queue>
#include <string>
#include <cstring>
#include <map>
#include <set>
#define PI acos(-1.0)
#define mem(a,b) memset(a,b,sizeof(a))
#define sca(a) scanf("%d",&a)
#define pri(a) printf("%d\n",a)
#define MM 1000002
#define MN 22005
#define INF 168430090
using namespace std;
typedef long long ll;
int n,m,cnt,d[MN],head[MM],go[MM],q[MM];
struct node
{
int v,w,next;
}e[MM];
void add(int u,int v,int w)
{
e[cnt].v=v; e[cnt].w=w; go[cnt]=cnt+1; //go数组的作用是记住反向边的邻接表下标,下同
e[cnt].next=head[u]; head[u]=cnt++;
e[cnt].v=u; e[cnt].w=0; go[cnt]=cnt-1; //反向边权值为0
e[cnt].next=head[v]; head[v]=cnt++;
}
int bfs()
{
mem(d,-1);
int left=0,right=0;
q[right++]=0; d[0]=0;
while(left<right) //找增广路
{
int u=q[left++];
for(int v=head[u];v!=-1;v=e[v].next)
{
if(d[e[v].v]==-1&&e[v].w)
{
d[e[v].v]=d[u]+1; //分层,越往后,层数越大
if(e[v].v!=n+1) q[right++]=e[v].v;
}
}
}
return d[n+1]!=-1;
}
int dfs(int u,int Min)
{
int sum,duolu=0;
if(u==n+1) return Min;
for(int v=head[u];v!=-1&&Min-duolu>0;v=e[v].next) //Min-duolu这个多路增广的做法真神!
if(e[v].w&&d[e[v].v]==d[u]+1&&(sum=dfs(e[v].v,min(Min-duolu,e[v].w))))
{
e[v].w-=sum;
e[go[v]].w+=sum;
duolu+=sum;
}
return duolu;
}
void Dinic()
{
int tmp,ans=0;
while(bfs())
{
while(tmp=dfs(0,INF))
ans+=tmp;
}
printf("%d\n",ans);
}
int main()
{
scanf("%d%d",&n,&m);
int u,v,w,i,a,b;
mem(head,-1);
for(i=1;i<=n;i++)
{
scanf("%d%d",&a,&b);
add(0,i,a); add(i,n+1,b);
}
while(m--)
{
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
}
Dinic();
return 0;
}