ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

TopCoder SRM 570 Div1 CurvyonRails

2020-09-07 12:00:20  阅读:241  来源: 互联网

标签:CurvyonRails ++ rep 570 field que TopCoder 代价 dis


TopCoder SRM 570 Div1 CurvyonRails

题意: 一个\(n\times m\)的网格图,其中有一些点需要建铁路,有一些点为关键点,在关键点上修直铁路会产生1的代价,求最小的代价

由于\(n,m\leq 25\)显然不可以插头\(\text{dp}\)。。。

考虑轨道联通实际上类似网络流的形式

考虑一个常见的思路: 网格图可以简化为二分图 然后 跑网络流

先不考虑代价的问题,判断是否存在合法方案

每个格子要有两条出边,因此可以让\(S\)向左侧点连边权为2的边,右侧点向\(T\)连边权为2的边

然后可以让每个左侧点向相邻的右侧点连边,即考虑了联通关系

下面考虑代价的计算,加入边的代价,即为费用流

连同向边会产生代价,因此考虑为每个节点新增两个节点,表示向上下/左右连边

对于让原节点对于新增的上下和左右节点 分别连两条代价为0和1的边

这样如果流了同向边,就会产生代价

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair <int,int> Pii;
#define pb push_back
#define mp make_pair
#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)
#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)
template <class T> inline void cmin(T &a,T b){ ((a>b)&&(a=b)); }
template <class T> inline void cmax(T &a,T b){ ((a<b)&&(a=b)); }

char IO;
int rd(){
	int s=0;
	int f=0;
	while(!isdigit(IO=getchar())) if(IO=='-') f=1;
	do s=(s<<1)+(s<<3)+(IO^'0');
	while(isdigit(IO=getchar()));
	return f?-s:s;
}

const int N=25*30*3,M=N<<3,INF=1e9+10;

int n,m,k;
int a[30][30];

// Max Flow Min Cost

int id[30][30][2];
struct Edge{
	int to,nxt,w,c;
}e[M];
int head[N],ecnt,S,T,V;
void Clear(){
	rep(i,1,V) head[i]=0;
	ecnt=1,V=0;
}
void AddEdge(int u,int v,int w,int c) {
	e[++ecnt]=(Edge){v,head[u],w,c};
	head[u]=ecnt;
}
void Link(int u,int v,int w,int c=0){ AddEdge(u,v,w,c),AddEdge(v,u,0,-c); }
#define erep(u,i) for(int i=head[u],v=e[i].to,w=e[i].w,c=e[i].c;i;i=e[i].nxt,v=e[i].to,w=e[i].w,c=e[i].c)

int dis[N];
int SPFA(){
	static int inq[N];
	static queue <int> que;
	rep(i,1,V) dis[i]=INF;
	que.push(S),dis[S]=0;
	while(!que.empty()) {
		int u=que.front(); que.pop();
		inq[u]=0;
		erep(u,i) if(w && dis[v]>dis[u]+c) {
			dis[v]=dis[u]+c;
			if(!inq[v]) inq[v]=1,que.push(v);
		}
	}
	return dis[T]<INF;
}
int Dfs(int u,int in) {
	if(u==T) return in;
	int out=0,t=dis[u]; dis[u]=INF;
	erep(u,i) if(w && dis[v]==t+c) {
		int t=Dfs(v,min(in-out,w));
		e[i].w-=t,e[i^1].w+=t,out+=t;
		if(in==out) break;
	}
	if(out) dis[u]=t;
	return out;
}

Pii Dinic(){
	int flow=0,cost=0;
	while(SPFA()) 
		for(int t;(t=Dfs(S,INF));) flow+=t,cost+=dis[T]*t;
	return mp(flow,cost);
}

class CurvyonRails {
	public:
		int getmin(vector <string> field) {
			n=field.size(),m=field[0].size();
			rep(i,0,n-1) rep(j,0,m-1) a[i+1][j+1]=field[i][j];
			k=0,Clear();
			rep(i,1,n) rep(j,1,m) if(a[i][j]!='w') {
				k++;
				rep(d,0,1) id[i][j][d]=++V;
			}
			S=++V,T=++V;
			rep(i,1,n) rep(j,1,m) if(a[i][j]!='w') {
				if((i+j)&1){
					Link(S,++V,2,0);
					rep(d,0,1) {
						Link(V,id[i][j][d],1,0);
						Link(V,id[i][j][d],1,a[i][j]=='C');
						// 如果两条走了同向,就会产生1的代价
					}
					if(i<n && a[i+1][j]!='w') Link(id[i][j][0],id[i+1][j][0],1,0);
					if(j<m && a[i][j+1]!='w') Link(id[i][j][1],id[i][j+1][1],1,0);
				} else {
					Link(++V,T,2,0);
					rep(d,0,1) {
						Link(id[i][j][d],V,1,0);
						Link(id[i][j][d],V,1,a[i][j]=='C');
						// 如果两条走了同向,就会产生1的代价
					}
					if(i<n && a[i+1][j]!='w') Link(id[i+1][j][0],id[i][j][0],1,0);
					if(j<m && a[i][j+1]!='w') Link(id[i][j+1][1],id[i][j][1],1,0);
				}
			}
			Pii ans=Dinic();
			if(ans.first!=k) return -1;
			return ans.second;
		}
};
//Powered by KawigiEdit 2.1.4 (beta) modified by pivanof!

标签:CurvyonRails,++,rep,570,field,que,TopCoder,代价,dis
来源: https://www.cnblogs.com/chasedeath/p/13626071.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有