zoukankan      html  css  js  c++  java
  • bzoj1927: [Sdoi2010]星际竞速

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1927

    思路:拆点拆成x和x'

    S向x'连边,容量为1,费用为定位时间

    S向x连边,容量为1,费用为0

    对于原图的边u->v

    u向v‘连边,容量为1,费用为时间

    x’向T连边,容量为1,费用为0;

    跑一遍费用流即可

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    const int maxn=1610,maxm=200010;
    using namespace std;
    int n,m,A[maxn],pre[maxm],now[maxn],son[maxm],val[maxm],cost[maxm],from[maxm],tot=1;
    int S=maxn-2,T=maxn-1,dis[maxn],q[maxm+10],head,tail,last[maxn],minc,flow;
    bool bo[maxn];
    struct Edge{int x,y,z;}E[maxm];
    void add(int a,int b,int c,int d){pre[++tot]=now[a],now[a]=tot,from[tot]=a,son[tot]=b,val[tot]=c,cost[tot]=d;}
    void ins(int a,int b,int c,int d){add(a,b,c,d),add(b,a,0,-d);}
    int p0(int x){return x<<1;}
    int p1(int x){return (x<<1)|1;}
    
    bool spfa(){
    	memset(dis,63,sizeof(dis));int inf=dis[0];
    	memset(bo,0,sizeof(bo));
    	q[tail=1]=S,dis[S]=head=0;
    	while (head!=tail){
    		if (++head>maxm) head=1;
    		int x=q[head];
    		for (int y=now[x];y;y=pre[y])
    			if (val[y]>0&&dis[son[y]]>dis[x]+cost[y]){
    				dis[son[y]]=dis[x]+cost[y],last[son[y]]=y;
    				if (!bo[son[y]]){
    					if (++tail>maxm) tail=1;
    					q[tail]=son[y],bo[son[y]]=1;
    				}
    			}
    		bo[x]=0;
    	}
    	return dis[T]<inf;
    }
    
    void find(){
    	int lim=1e9;
    	for (int x=T,y;x!=S;x=from[y]) y=last[x],lim=min(lim,val[y]);
    	flow+=lim;
    	for (int x=T,y;x!=S;x=from[y]) y=last[x],minc+=lim*cost[y],val[y]-=lim,val[y^1]+=lim;
    }
    
    int main(){
    	scanf("%d%d",&n,&m);
    	for (int i=1;i<=n;i++) scanf("%d",&A[i]);
    	for (int i=1,x,y,z;i<=m;i++){
    		scanf("%d%d%d",&x,&y,&z);
    		if (x>y) swap(x,y);
    		E[i]=(Edge){x,y,z};
    	}
    	for (int i=1;i<=n;i++) ins(S,p1(i),1,A[i]),ins(S,p0(i),1,0),ins(p1(i),T,1,0);
    	for (int i=1;i<=m;i++) ins(p0(E[i].x),p1(E[i].y),1,E[i].z);
    	while (spfa()) find();
    	//spfa();
    	//for (int i=1;i<=n;i++) printf("%d
    ",from[last[i]]);
    	printf("%d
    ",minc);
    	return 0;
    }


  • 相关阅读:
    Linux命令笔记
    Linux服务安装集合(1)
    浅谈GIT之通讯协议
    浅谈GIT之底层对象理解
    友情链接
    当黑客被抓是种怎样的体验?
    PHP 中 include 和 require 的区别详解
    论假如有一台无限算力的主机
    msf渗透安卓手机
    aws ec2 安装Elastic search 7.2.0 kibana 并配置 hanlp 分词插件
  • 原文地址:https://www.cnblogs.com/thythy/p/5493458.html
Copyright © 2011-2022 走看看