zoukankan      html  css  js  c++  java
  • BZOJ 3931 (网络流+最短路)

    题面

    传送门

    分析

    考虑网络流

    注意到数据包走的是最短路,所以我们只需要考虑在最短路上的边

    由于最短路可能有多条,我们先跑一遍Dijkstra,然后再(O(m)) 遍历每条边(u,v,w)

    如果dist[u]=dist[v]+w,则这条边肯定在最短路上

    然后点的容量限制可以用拆点来解(常见套路),从u向u+n连边,容量为c[u]

    原图中的边(u,v)在新图中变成边(u+n,v)

    然后Dinic求最大流即可

    代码

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm> 
    #include<vector>
    #include<queue>
    #define maxn 1005
    #define maxm 200005
    #define INF 0x3f3f3f3f3f3f3f3f
    using namespace std;
    int n,m;
    vector<pair<int,long long> >G[maxn];
    struct node{
    	int x;
    	long long d;
    	node(){
    		
    	}
    	node(int u,long long dis){
    		x=u;
    		d=dis;
    	}
    	friend bool operator < (node p,node q){
    		return p.d>q.d;
    	} 
    };
    long long dist[maxn];
    int used[maxn];
    void dijkstra(){
    	priority_queue<node>q;
    	q.push(node(1,0));
    	memset(dist,0x3f,sizeof(dist));
    	dist[1]=0;
    	while(!q.empty()){
    		node now=q.top();
    		q.pop();
    		int x=now.x; 
    		if(used[x]) continue;
    		used[x]=1;
    		int l=G[x].size();
    		for(int i=0;i<l;i++){
    			int y=G[x][i].first;
    			int len=G[x][i].second;
    			if(dist[y]>dist[x]+len){
    				dist[y]=dist[x]+len;
    				q.push(node(y,dist[y]));
    			}
    		}
    	}
    }
    
    long long c[maxn];
    struct edge{
    	int from;
    	int to;
    	int next;
    	long long flow;
    }E[maxm<<1];
    int sz=1;
    int head[maxn];
    void add_edge(int u,int v,long long w){
    //	printf("%d->%d : %d
    ",u,v,w);
    	sz++;
    	E[sz].from=u;
    	E[sz].to=v;
    	E[sz].next=head[u];
    	E[sz].flow=w;
    	head[u]=sz;
    	sz++;
    	E[sz].from=v;
    	E[sz].to=u;
    	E[sz].next=head[v];
    	E[sz].flow=0;
    	head[v]=sz;
    }
    
    int deep[maxn];
    bool bfs(int s,int t){
    	queue<int>q;
    	memset(deep,0,sizeof(deep));
    	q.push(s);
    	deep[s]=1;
    	while(!q.empty()){
    		int x=q.front();
    		q.pop();
    		for(int i=head[x];i;i=E[i].next){
    			int y=E[i].to;
    			if(E[i].flow&&!deep[y]){
    				deep[y]=deep[x]+1;
    				if(y==t) return 1;
    				q.push(y);
    			} 
    		}
    	}
    	return 0;
    }
    
    long long dfs(int x,int t,long long minf){
    	if(x==t) return minf;
    	long long k,rest=minf;
    	for(int i=head[x];i;i=E[i].next){
    		int y=E[i].to;
    		if(E[i].flow&&deep[y]==deep[x]+1){
    			k=dfs(y,t,min(rest,E[i].flow));
    			if(k==0) deep[y]=0;
    			E[i].flow-=k;
    			E[i^1].flow+=k;
    			rest-=k; 
    		}
    	}
    	return minf-rest;
    }
    
    long long dinic(int s,int t){
    	long long maxflow=0,nowflow=0;
    	while(bfs(s,t)){
    		while(nowflow=dfs(s,t,INF)) maxflow+=nowflow;
    	}
    	return maxflow;
    }
    
    int main(){
    	int u,v;
    	long long w;
    	scanf("%d %d",&n,&m);
    	for(int i=1;i<=m;i++){
    		scanf("%d %d %lld",&u,&v,&w);
    		G[u].push_back(make_pair(v,w));
    		G[v].push_back(make_pair(u,w));
    	} 
    	for(int i=1;i<=n;i++) scanf("%lld",&c[i]);
    	c[1]=c[n]=INF;
    	dijkstra();
    	for(int i=1;i<=n;i++){
    		add_edge(i,i+n,c[i]);
    	}
    	for(int i=1;i<=n;i++){
    		for(int j=0;j<G[i].size();j++){
    			int y=G[i][j].first;
    			long long len=G[i][j].second;
    			if(dist[y]==dist[i]+len){
    				add_edge(i+n,y,INF);
    			}
    		}
    	}
    	printf("%lld
    ",dinic(1,n*2));
    }
    
  • 相关阅读:
    致初学者:PHP比ASP优秀的七个理由
    有情人终成眷属为好友hualex2006.12.9结婚祝福
    有情人终成眷属为好友hualex2006.12.9结婚祝福
    各种查找算法效率比较
    实习三 树、二叉树及其应用 (题目:唯一地确定一棵二叉树 )
    hdu 2188 选拔志愿者(博弈)
    hdu 1050Moving Tables(贪心)
    实习一 线性表及其应用 (题目:一元稀疏多项式的加法运算 )
    实习六 农夫过河问题
    实习二 栈、队列和递归算法设计 (题目:停车场管理 )
  • 原文地址:https://www.cnblogs.com/birchtree/p/10333221.html
Copyright © 2011-2022 走看看