zoukankan      html  css  js  c++  java
  • [SDOI2010][bzoj1927] 星际竞速 [最小路径覆盖+费用流]

    题面

    传送门

    思路

    仔细观察题目要求的东西,发现就是求一个最小路径覆盖,只不过可以跳跃(就是那个鬼畜的超级跳跃)

    那么就直接上最小路径覆盖模版

    对每个点,拆成两个点$X_i$和$Y_i$,建立超级源超级汇S,T

    连边$left(S,X_i ight)$,$left(Y_i,T ight)$,流量1费用0

    对于原图中的边$left(i,j ight)$,连边$left(X_i,Y_j ight)$,流量1费用为原本的时间

    对于超级跳跃,连边$left(S,Y_i ight)$,流量1费用为跳跃时间

    跑S-T最小费用最大流即可

    Code

    在luogu+COGS上莫名其妙T了

    但是bzoj2400ms过

    interesting......

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define inf 1e9
    using namespace std;
    inline int read(){
    	int re=0,flag=1;char ch=getchar();
    	while(ch>'9'||ch<'0'){
    		if(ch=='-') flag=-1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9') re=(re<<1)+(re<<3)+ch-'0',ch=getchar();
    	return re*flag;
    }
    int first[2010],dis[2010],vis[2010],n,m,cnt=-1,ans;
    struct edge{
    	int to,next,w,cap;
    }a[150010];
    inline void add(int u,int v,int w,int cap){
    	a[++cnt]=(edge){v,first[u],w,cap};first[u]=cnt;
    	a[++cnt]=(edge){u,first[v],-w,0};first[v]=cnt;
    }
    int q[100010];
    bool spfa(int s,int t){
    	int head=0,tail=1,i,u,v,w;
    	memset(dis,-1,sizeof(dis));memset(vis,0,sizeof(vis));
    	q[0]=t;dis[t]=0;vis[t]=1;
    	while(head<tail){
    		u=q[head++];vis[u]=0;
    		for(i=first[u];~i;i=a[i].next){
    			v=a[i].to;w=a[i].w;
    			if(a[i^1].cap&&((dis[v]==-1)||(dis[v]>dis[u]-w))){
    				dis[v]=dis[u]-w;
    				if(!vis[v]) q[tail++]=v,vis[v]=1;
    			}
    		}
    	}
    	return ~dis[s];
    }
    int dfs(int u,int t,int limit){
    	if((u==t)||(!limit)){vis[u]=1;return limit;}
    	int i,v,f,flow=0,w;vis[u]=1;
    	for(i=first[u];~i;i=a[i].next){
    		v=a[i].to;w=a[i].w;
    		if(dis[v]==dis[u]-w&&a[i].cap&&!vis[v]){
    			if(!(f=dfs(v,t,min(limit,a[i].cap)))) continue;
    			a[i].cap-=f;a[i^1].cap+=f;
    			ans+=f*w;flow+=f;limit-=f;
    			if(!limit) return flow;
    		}
    	}
    	return flow;
    }
    int zkw(int s,int t){
    	int re=0;
    	while(spfa(s,t)){
    		vis[t]=1;
    		while(vis[t]){
    			memset(vis,0,sizeof(vis));
    			re+=dfs(s,t,inf);
    		}
    	}
    	return re;
    }
    int jump[1010];
    int main(){
    	freopen("starrace8.in","r",stdin);
    	freopen("starrace.out","w",stdout);
    	memset(first,-1,sizeof(first));
    	n=read();m=read();int i,t1,t2,t3;
    	for(i=1;i<=n;i++) jump[i]=read(),add(0,i+n,jump[i],1);
    	for(i=1;i<=m;i++){
    		t1=read();t2=read();t3=read();
    		if(t1>t2) swap(t1,t2);
    		add(t1,t2+n,t3,1);
    	}
    	for(i=1;i<=n;i++) add(0,i,0,1),add(i+n,(n<<1)+1,0,1);
    	zkw(0,(n<<1)+1);
    	printf("%d
    ",ans);
    }
    
  • 相关阅读:
    根据条件把一个字符串拆分成几个字符串
    【SQLServer】SQL Server 2000的分页方法(SQL篇)
    【C#】NHibernate下实现SQL2000分页(SQL篇)
    【Oracle】仿Oracle Sequence的自定义年份Sequence(适合任何数据库)
    【Oracle】仿Oracle Sequence的自定义年份Sequence(适合任何数据库)(续)
    【C#】NHibernate下为SQL Server添加随机排序
    【LoadRunner】LoadRunner 9.5回放Windows Socket时CPU 100%
    【CSS】CSS Cookbook例子:创建水平导航菜单
    【CSS】CSS Cookbook例子:创建文字导航菜单和翻转特效
    【Flex】实现模块顺序执行
  • 原文地址:https://www.cnblogs.com/dedicatus545/p/8743381.html
Copyright © 2011-2022 走看看