BZOJ 3931 网络吞吐量 (最短路+最大流)

来源:互联网 发布:管家婆软件服务电话 编辑:程序博客网 时间:2024/05/22 15:22

题目大意:

中文题,题目即题意。


解题思路:

先求最短路,只有在最短路上的边才是在网络里的。

然后把这些边上的点拆边。

求最大流。


学习到了优先队列。

(不太会)

第一次WA是挂在我自己宏定义那个max上……

#include<cstdio>#include<cstring>#include<string>#include<cmath>#include<iostream>#include<algorithm>#include<set>#include<queue>#define LL long long#define db double#define maxn 10000000#define EPS 1e-15//#define max(a,b) ((a>b)?(a):(b))//#define min(a,b) ((a<b)?(a):(b))#define pa pair<int,int>#define inf 100000000000000LLusing namespace std;int n,m,cnt,T;LL dis[505];int last[1005],cur[1005],q[1005],h[1005];int a[100005],b[100005],d[100005];struct edge{int to,next; LL w;}e[200005];void insert(int u,int v,LL w){e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].w=w;}void dijkstra(){priority_queue<pa,vector<pa>,greater<pa> >q;for(int i=1;i<=n;i++)dis[i]=inf;dis[1]=0;q.push(make_pair(0,1));while(!q.empty()){int now=q.top().second;q.pop();for(int i=last[now];i;i=e[i].next)if(dis[now]+e[i].w<dis[e[i].to]){dis[e[i].to]=dis[now]+e[i].w;q.push(make_pair(dis[e[i].to],e[i].to));}}}bool dinic_bfs(){int head=0,tail=1;for (int i=1;i<=2*n;i++) h[i]=-1;q[0]=1; h[1]=0;while (head!=tail){int x=q[head]; head++;for (int i=last[x];i;i=e[i].next)if (e[i].w && h[e[i].to]==-1){h[e[i].to]=h[x]+1;q[tail++]=e[i].to;}}return h[2*n]!=-1;}LL dinic_dfs(int x,LL f){if (x==2*n) return f;LL w,used=0;for (int i=cur[x];i;i=e[i].next)if (h[e[i].to]==h[x]+1){w=dinic_dfs(e[i].to,min(f-used,e[i].w));e[i].w-=w;e[i^1].w+=w;used+=w; if (used==f) return f;}if (!used) h[x]=-1;return used;}LL dinic_flow(){LL ans=0;while (dinic_bfs()){for (int i=1;i<=2*n;i++) cur[i]=last[i];ans+=dinic_dfs(1,inf);}return ans;}int main(){scanf("%d%d",&n,&m);for (int i=1;i<=m;i++){scanf("%d%d%d",&a[i],&b[i],&d[i]);insert(a[i],b[i],d[i]);insert(b[i],a[i],d[i]);}dijkstra();for(int i=1;i<=n;i++)last[i]=0;cnt=1;for(int i=1;i<=m;i++){if(dis[a[i]]+d[i]==dis[b[i]]){insert(a[i]+n,b[i],inf);insert(b[i],a[i]+n,0);}if(dis[b[i]]+d[i]==dis[a[i]]){insert(b[i]+n,a[i],inf);insert(a[i],b[i]+n,0);}}int c;for(int i=1;i<=n;i++){scanf("%d",&c);if(i!=1 && i!=n)insert(i,i+n,c);else insert(i,i+n,inf);insert(i+n,i,0);}printf("%lld\n",dinic_flow());return 0;}




0 0