题意:给定一个网格,一些格子是障碍不用管,剩余的格子是城市,你可以修建铁路,铁路的形状可以是直的或者弯的,也就是说可以以这个点为节点连接它四联通的其中两个方块。要求用一个或多个环来覆盖所有城市。对于有些关键点,如果这里是直轨道,会付出1的代价,如果不能覆盖,输出-1,否则输出最小代价。

这次该最小费用流了。x先考虑怎么判断有无解。很明显,既然是棋盘,想不染色不二分图都难。染成黑白后,对于黑点,S向其连2,黑点向周围的白点连1,白点向T连2,判断是否满流就好了。那么怎么计算代价呢?我们发现,如果要付出代价,那么一定是两个开口都给了同一列或者同一行,为了对此限制,我们拆点,分别管辖行和列。

如果这个点是黑关键点,我们向行对应的分身连一个容量1,费用0的边,再连一个容量1,费用1的边,表示如果只用一条边,不会产生费用,否则产生两条边的费用。列的话同理。

白关键点就不赘述了,其实也就是相较于反了一下。对于普通点,直接相对应的两个点分别连(2,0)就好了(因为没有限制),然后黑连向对应的白就好了。

跑费用流,不满流无解,满流输出费用即可。

 #include<bits/stdc++.h>
using namespace std;
#define INF 1e9
#define N 5005
#define id(i,j) ((i-1)*m+j)
int n,m,TOT,S,T,P,head[N],d[N],a[N],p[N],cnt;
bool vis[N];
queue<int>q;
char field[N][N];
inline int read(){
int x=,f=; char a=getchar();
while(a<'' || a>'') {if(a=='-') f=-; a=getchar();}
while(a>='' && a<='') x=x*+a-'',a=getchar();
return x*f;
}
struct edges{
int fr,to,cap,flow,cost,next;
}e[*N]; inline void insert(int u,int v,int f,int c){
e[cnt]=(edges){u,v,f,,c,head[u]};head[u]=cnt++;
e[cnt]=(edges){v,u,,,-c,head[v]};head[v]=cnt++;
}
inline bool spfa(){
memset(d,0x3f,sizeof(d));
d[S]=; a[S]=INF; q.push(S);
while(!q.empty()){
int x=q.front(); q.pop(); vis[x]=;
for(int i=head[x];i>=;i=e[i].next)
if(d[e[i].to]>d[x]+e[i].cost && e[i].flow<e[i].cap){
d[e[i].to]=d[x]+e[i].cost; p[e[i].to]=i;
a[e[i].to]=min(a[x],e[i].cap-e[i].flow);
if(!vis[e[i].to]) vis[e[i].to]=,q.push(e[i].to);
}
}
return d[T]<INF;
}
inline int mincf(){
int u=T;
while(u!=S){
e[p[u]].flow+=a[T];
e[p[u]^].flow-=a[T];
u=e[p[u]].fr;
}
TOT-=a[T];
return a[T]*d[T];
} int main(){
n=read(); m=read();
for(int i=;i<=n;i++)
scanf("%s",field[i]+);
S=; T=*n*m+; P=n*m; TOT=;
memset(head,-,sizeof(head));
for(int i=;i<=n;i++)
for(int j=;j<=m;j++){
if(field[i][j]=='w') continue;
if((i+j)%==){
insert(S,id(i,j),,); TOT+=;
if(field[i][j]!='C') insert(id(i,j),id(i,j)+*P,,),insert(id(i,j),id(i,j)+P,,);
else {
insert(id(i,j),id(i,j)+P,,); insert(id(i,j),id(i,j)+P,,);
insert(id(i,j),id(i,j)+*P,,); insert(id(i,j),id(i,j)+*P,,);
}
if(j-> && field[i][j-]!='w') insert(id(i,j)+P,id(i,j-)+P,,);
if(j+<=m && field[i][j+]!='w' ) insert(id(i,j)+P,id(i,j+)+P,,);
if(i-> && field[i-][j]!='w') insert(id(i,j)+*P,id(i-,j)+*P,,);
if(i+<=n && field[i+][j]!='w') insert(id(i,j)+*P,id(i+,j)+*P,,);
}else{
insert(id(i,j),T,,);
if(field[i][j]!='C') insert(id(i,j)+*P,id(i,j),,),insert(id(i,j)+P,id(i,j),,);
else{
insert(id(i,j)+P,id(i,j),,); insert(id(i,j)+P,id(i,j),,);
insert(id(i,j)+*P,id(i,j),,); insert(id(i,j)+*P,id(i,j),,);
}
}
}
int ans=;
while(spfa()) ans+=mincf();
if(TOT) ans=-;
printf("%d\n",ans);
}

Topcoder SRM570 900 CurvyonRails的更多相关文章

  1. Topcoder SRM570 D1L3 CurvyonRails

    几个样例: 5 5wCCwwwCC....w......www..wReturns: 0 3 3C.w....C.Returns: 1 21 20CC..CCCw.CwC..CC.w.CC.CCCwC ...

  2. Topcoder口胡记 SRM 562 Div 1 ~ SRM 599 Div 1

    据说做TC题有助于提高知识水平? :) 传送门:https://284914869.github.io/AEoj/index.html 转载请注明链接:http://www.cnblogs.com/B ...

  3. Topcoder SRM 618 Div2 --900

    题意:给定两个NxN的棋盘,每个棋盘都有一个‘车’的摆放状态,问进行若干次交换,能否使棋盘1变为棋盘2. 交换规则:每次选两个‘车’,坐标分别为(r1,c1),(r2,c2),如果r1<r2并且 ...

  4. TopCoder SRM 559 Div 1 - Problem 900 CircusTents

    传送门:https://284914869.github.io/AEoj/559.html 题目简述: n个实心圆,两两没有交集,在第一个圆上找一个点,使得它到另外一个圆上某个点的最短距离的最小值尽量 ...

  5. TopCoder SRM 701 Div2 Problem 900 ThueMorseGame(博弈+预处理)

    题意  Alice和Bob在玩一个游戏,Alice先手. 每次一个人可以从一堆式子中拿走任意数量(不超过m)的式子. 取走最后一颗式子的人胜利. 当一个取完某一步的时候剩下的石子数量的二进制表示中1的 ...

  6. TopCoder[SRM587 DIV 1]:ThreeColorability(900)

    Problem Statement      There is a H times W rectangle divided into unit cells. The rows of cells are ...

  7. TopCoder入门

    TopCoder入门 http://acmicpc.info/archives/164?tdsourcetag=s_pctim_aiomsg 本文根据经典的TC教程完善和改编.TopCoder:htt ...

  8. ORA-00494: enqueue [CF] held for too long (more than 900 seconds) by 'inst 1, osid 5166'

    凌晨收到同事电话,反馈应用程序访问Oracle数据库时报错,当时现场现象确认: 1. 应用程序访问不了数据库,使用SQL Developer测试发现访问不了数据库.报ORA-12570 TNS:pac ...

  9. TopCoder kawigiEdit插件配置

    kawigiEdit插件可以提高 TopCoder编译,提交效率,可以管理保存每次SRM的代码. kawigiEdit下载地址:http://code.google.com/p/kawigiedit/ ...

随机推荐

  1. linux杀死jobs的正确方法

    输入命令:logout 终端显示:There are stopped jobs. 解决方法: 输入命令:jobs 终端显示:[]+ Stopped vim /etc/network/interface ...

  2. Zabbix3.x安装图解教程

    准备知识: Zabbix3.x比较之前的2.0界面有了很大的变化,但是安装部署过程与2.x基本完全一样. 1.Zabbix2.x安装图解教程 http://www.osyunwei.com/archi ...

  3. 存储过程里面使用in变量列表异常的处理

    在写一个存储过程的时候,由于需要用到类似:select id,name from tablename where id in(id1,id2,id3...)的查询语句,同时括号里面的变量是拼接得到的, ...

  4. 通知Notification

    步骤: 1.调用getSystemService()获取NotificationManager:NotificationManager manager = (NotificationManager)g ...

  5. js跳转

    window.location.reload(); //刷新当前页,参数保留

  6. 【leetcode❤python】 125. Valid Palindrome

    #-*- coding: UTF-8 -*- class Solution(object):    def isPalindrome(self, s):        ""&quo ...

  7. JQuery获取浏览器窗口的可视区域高度和宽度,滚动条高度

    alert($(window).height()); //浏览器时下窗口可视区域高度 alert($(document).height()); //浏览器时下窗口文档的高度 alert($(docum ...

  8. Codeforces Round #389 (Div. 2, Rated, Based on Technocup 2017 - Elimination Round 3) D. Santa Claus and a Palindrome STL

    D. Santa Claus and a Palindrome time limit per test 2 seconds memory limit per test 256 megabytes in ...

  9. 转行做开发的Wiki:找好方向

    案 我是一个从建筑行业转行过来的后端工程师,转行来写代码了.最近发现经常有同学和网上的朋友问我一些转行的问题,零零散散地回答莫不如写一篇文章,以后回答此类问题就方便多了. 我的专业是给排水,属于非常传 ...

  10. linux环境初始化 用户问题

    linux 初始化系统配置(centos6) (2013-04-03 13:19:15) 转载▼   分类: linux 这篇博文是从别处转来的,原文地址http://zhoualine.iteye. ...