您的位置:首页 > 理论基础 > 计算机网络

BZOJ 3931 [CQOI2015]网络吞吐量 最短路+最大流

2017-03-13 08:59 417 查看
题目大意:每个点有流量限制vi,只有在从起点到终点的最短路径上的边才可以走,求最大流量。

将每个点分成入点与出点,入点与出点连一条vi的边(除起点与终点),最短路径上的边的流量为INF。

1.网络流建图时若边不从0开始存一定要注意异或找反边有可能是错误的

2.数组又开小了QAQ

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define INF (1ll<<60)
#define N 2005
using namespace std;
#define int long long
struct Edge {
int from,to,nxt,cap;
}e[N*400];
int S,T,n,m,top=-1,v
,fir
,d
,cur
;
bool k
;
void Add_Edge(int from,int to,int cap) {
e[++top].from=from;
e[top].to=to;
e[top].cap=cap;
e[top].nxt=fir[from];
fir[from]=top;
e[++top].from=to;
e[top].to=from;
e[top].cap=0;
e[top].nxt=fir[to];
fir[to]=top;
return ;
}
struct Node {
int ord,val;
Node(int _,int __):ord(_),val(__){}
bool operator < (const Node& rhs) const {return val>rhs.val;}
};
void Dijkstra() {
priority_queue<Node> q;
for(int i=1;i<=n;i++) d[i]=INF;
d[1]=0;
q.push(Node(1,0));
while(!q.empty()) {
Node tmp=q.top(); q.pop();
int x=tmp.ord,val=tmp.val;
if(k[x]) continue;
k[x]=true;
for(int i=fir[x];i;i=e[i].nxt) {
if(d[e[i].to]<=val+e[i].cap) continue;
//printf("***");
d[e[i].to]=val+e[i].cap;
q.push(Node(e[i].to,d[e[i].to]));
}
}
return ;
}
bool bfs() {
memset(d,-1,sizeof d);
static int q
;
int l,r; l=r=0; q[r++]=S; d[S]=0;
while(l<r){
int x=q[l++];
for(int i=fir[x];i;i=e[i].nxt) {
if(e[i].cap<=0 || d[e[i].to]!=-1) continue;
q[r++]=e[i].to;
d[e[i].to]=d[x]+1;
if(e[i].to==T) return true;
}
}
return false;
}
int dfs(int x,int now) {
if(!now || x==T) return now;
int flow=0,f;
for(int& i=cur[x];i;i=e[i].nxt) {
if(d[e[i].to]!=d[x]+1) continue;
f=dfs(e[i].to,min(now,e[i].cap));
if(f<1) continue;
flow+=f; now-=f;
e[i].cap-=f; e[i^1].cap+=f;
if(!now) break;
}
return flow;
}
int Dinic() {
int ans=0;
while(bfs()){
for(int i=0;i<=T;i++) cur[i]=fir[i];
ans+=dfs(S,INF);
}
return ans;
}
#undef int
int main() {
#define int long long
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;i++) {
int x,y,z;
scanf("%lld%lld%lld",&x,&y,&z);
e[i].from=x;
e[i].to=y;
e[i].cap=z;
e[i].nxt=fir[x];
fir[x]=i;
e[i+m].from=y;
e[i+m].to=x;
e[i+m].cap=z;
e[i+m].nxt=fir[y];
fir[y]=i+m;
}
for(int i=1;i<=n;i++) scanf("%lld",&v[i]);
Dijkstra();
memset(fir,0,sizeof fir);
top=((m*2)&1 ? m*2 : m*2+1), S=1, T=2*n+2;
for(int i=1;i<=m*2;i++)
if(d[e[i].from]+e[i].cap==d[e[i].to])
Add_Edge(2*e[i].from+1,2*e[i].to,INF);
for(int i=2;i<n;i++) Add_Edge(2*i,2*i+1,v[i]);
Add_Edge(S,3,INF); Add_Edge(n*2,T,INF);
printf("%lld\n",Dinic());
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: