bzoj4501 旅行
题面:
小C来到了F国,小C想好好地参观F国。F国可以看一个有n个点m条边的有向无环图,小C刚开始站在1号点。假设现在小C站在x号点:
1.点x没有出边,结束旅游。
2.点x有o条出边,小C等概率地选一条边走过去。
小J是小C的好朋友,小J可以使用魔法让一些边消失,但是有一些限制(x,y):第y条边如果被删掉了,那么第x条边也会受到影响,导致第x条边被删掉。
现在小J想知道,如何删边使得小C所经过的边数期望最大。
第一行三个整数,n,m,k(1 <= n <= 50, 0 <= m <= 500, 0 <= k <= 2000),代表有n个点,m条边,k个限制。
接下来m行,第i行代表第i条边x,y(1 <= x, y <= n),方向是从x到y。
接下来k行,每行有两个整数x,y(1 <= x, y <= m),代表限制。
保证图是有向无环的,保证对于每个限制(x,y),第x条边和第y条边的起点是相同的。可能有重边,限制可能重复。
1 <= n <= 50, 0 <= m <= 500, 0 <= k <= 2000
首先既然是有向无环图,那么如果最优决策中从点x出发的期望步数最多,且从x向y有一条边,必然从y出发的期望步数也达到最多,那么我们按拓扑序依次求出从每个点出发的期望最大步数f[x]即可.
假设我们已经知道了从x出发能到达的所有点的f值,并选择了j条边保留,那么f[x]=1+sigma{f[y],保留的某条边从x指向y}/j,每保留一条边,分子和分母都会增加,相当于保留的边指向的f值的平均值最大,相当于01分数规划,二分这个平均值即可.二分之后每条边有一个权值,如果能选出一些边使得权值和大于0说明答案大于等于当前判断的值.那么接下来跑最大权闭合子图即可.
注意最大权闭合子图的建模是不需要对SCC缩点也能跑的,NOI植物大战僵尸是因为SCC不能选所以需要缩点.我比较简单无脑缩点直接上了于是飙到170行+...不过namespace大法吼啊….被调试续了1h,最后发现我把题读错了,限制的x,y是y删了导致x一定被删不是x删了导致y被删…..新技能get:调代码调不动的时候重新读一遍题有奇效!
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const double eps=1e-;
int cmp(double x){return x<-eps?-:x>eps;}
namespace DINIC{
const int maxn=,maxm=;
struct edge{
int to,next;double w;
}lst[maxm];int len=,first[maxn],_first[maxn];
void clear(){
memset(first,-,sizeof(first));len=;
}
void addedge(int a,int b,double w){
lst[len].to=b;lst[len].next=first[a];lst[len].w=w;first[a]=len++;
lst[len].to=a;lst[len].next=first[b];lst[len].w=;first[b]=len++;
}
int q[maxn],vis[maxn],dis[maxn],head,tail,T,s,t;
bool bfs(){
head=tail=;vis[s]=++T;dis[s]=;q[tail++]=s;
while(head!=tail){
int x=q[head++];
for(int pt=first[x];pt!=-;pt=lst[pt].next){
if(lst[pt].w>eps&&vis[lst[pt].to]!=T){
vis[lst[pt].to]=T;q[tail++]=lst[pt].to;dis[lst[pt].to]=dis[x]+;
}
}
}
if(vis[t]==T)memcpy(_first,first,sizeof(first));
return vis[t]==T;
}
double dfs(int x,double lim){
if(x==t)return lim;
double flow=,a;
for(int pt=_first[x];pt!=-;pt=lst[pt].next){
if(lst[pt].w>eps&&dis[lst[pt].to]==dis[x]+&&(a=dfs(lst[pt].to,min(lst[pt].w,lim-flow)))>eps){
lst[pt].w-=a;lst[pt^].w+=a;flow+=a;
if(cmp(flow-lim)==)return flow;
}
}
return flow;
}
double dinic(){
double ans=,x;
while(bfs())while((x=dfs(s,1e5))>eps)ans+=x;
return ans;
}
};
namespace Tarjan{
const int maxm=,maxn=;
struct edge{
int to,next;
}lst[maxm],lst2[maxm];int len=,first[maxn],len2=,first2[maxn];
void addedge(int a,int b){
lst[len].to=b;lst[len].next=first[a];first[a]=len++;
}
void addedge2(int a,int b){
lst2[len2].to=b;lst2[len2].next=first2[a];first2[a]=len2++;
}
int dfn[maxn],low[maxn],s[maxn],top,belong[maxn],tot,T;bool ins[maxn];
void dfs(int x){
dfn[x]=low[x]=++T;ins[x]=true;s[top++]=x;
for(int pt=first[x];pt;pt=lst[pt].next){
if(!dfn[lst[pt].to]){
dfs(lst[pt].to);
if(low[lst[pt].to]<low[x])low[x]=low[lst[pt].to];
}else if(ins[lst[pt].to]&&dfn[lst[pt].to]<low[x])low[x]=dfn[lst[pt].to];
}
if(dfn[x]==low[x]){
++tot;
do{
ins[s[--top]]=false;belong[s[top]]=tot;
}while(s[top]!=x);
}
}
void tarjan(int n,int m){
int x,y;
for(int i=;i<=m;++i){
scanf("%d%d",&x,&y);addedge(x,y);//选x必须选y
}
for(int i=;i<=n;++i){
if(!dfn[i])dfs(i);
}
for(int i=;i<=n;++i){
for(int pt=first[i];pt;pt=lst[pt].next){
if(belong[i]!=belong[lst[pt].to]){
addedge2(belong[i],belong[lst[pt].to]);
}
}
}
}
};
namespace Main{
const int maxm=,maxn=;
int n,m,k;
struct edge{
int to,next,num;
}lst[maxm];int len=,first[maxn];
void addedge(int a,int b,int i){
lst[len].to=b;lst[len].next=first[a];lst[len].num=i;first[a]=len++;
}
int sz[maxm];
bool vis[maxn];
double f[maxn];
double sum[maxm];
int scc[maxm];int tot=;
int sccused[maxm],T;
bool check(double ans){
DINIC::clear();using DINIC::addedge;using DINIC::s;using DINIC::t;
s=;t=m+;
double ori=;
for(int i=;i<=tot;++i){
int x=scc[i];
if(cmp(sum[x]-ans*sz[x])>=){
addedge(s,x,sum[x]-ans*sz[x]);ori+=sum[x]-ans*sz[x];
}
else addedge(x,t,ans*sz[x]-sum[x]);
}
using Tarjan::first2;using Tarjan::lst2;
for(int i=;i<=tot;++i){
for(int pt=first2[scc[i]];pt;pt=lst2[pt].next){
addedge(scc[i],lst2[pt].to,1e5);
}
}
return cmp(ori-DINIC::dinic())>;
}
void getf(int x){
using Tarjan::belong;
if(!first[x])f[x]=;
else{
tot=;++T;
for(int pt=first[x];pt;pt=lst[pt].next){
sum[belong[lst[pt].num]]+=f[lst[pt].to];
sz[belong[lst[pt].num]]++;
if(sccused[belong[lst[pt].num]]!=T){
sccused[belong[lst[pt].num]]=T;scc[++tot]=belong[lst[pt].num];
}
}
double l=,r=;
while(r-l>1e-){
double mid=(l+r)/2.0;
if(check(mid))l=mid;
else r=mid;
}
f[x]=l+;
}
}
void dfs(int x){
vis[x]=true;
for(int pt=first[x];pt;pt=lst[pt].next){
if(!vis[lst[pt].to])dfs(lst[pt].to);
}
getf(x);
}
void work(){
scanf("%d%d%d",&n,&m,&k);
int x,y;
for(int i=;i<=m;++i){
scanf("%d%d",&x,&y);addedge(x,y,i);
}
Tarjan::tarjan(m,k);
for(int i=;i<=n;++i){
if(!vis[i])dfs(i);
}
printf("%.10f\n",f[]);
}
};
int main(){
Main::work();
return ;
}
bzoj4501 旅行的更多相关文章
- BZOJ 3531: [Sdoi2014]旅行 [树链剖分]
3531: [Sdoi2014]旅行 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1685 Solved: 751[Submit][Status] ...
- vijos P1780 【NOIP2012】 开车旅行
描述 小\(A\)和小\(B\)决定利用假期外出旅行,他们将想去的城市从\(1\)到\(N\)编号,且编号较小的城市在编号较大的城市的西边,已知各个城市的海拔高度互不相同,记城市\(i\)的海拔高度为 ...
- 【BZOJ-1570】BlueMary的旅行 分层建图 + 最大流
1570: [JSOI2008]Blue Mary的旅行 Time Limit: 15 Sec Memory Limit: 162 MBSubmit: 388 Solved: 212[Submit ...
- codevs 1036 商务旅行(Targin求LCA)
传送门 Description 某首都城市的商人要经常到各城镇去做生意,他们按自己的路线去做,目的是为了更好的节约时间. 假设有N个城镇,首都编号为1,商人从首都出发,其他各城镇之间都有道路连接,任意 ...
- nyoj 71 独木舟上的旅行(贪心专题)
独木舟上的旅行 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 进行一次独木舟的旅行活动,独木舟可以在港口租到,并且之间没有区别.一条独木舟最多只能乘坐两个人,且乘客 ...
- 【bzoj3531】 [SDOI2014]旅行
题目描述 S国有N个城市,编号从1到N.城市间用N-1条双向道路连接,满足从一个城市出发可以到达其它所有城市.每个城市信仰不同的宗教,如飞天面条神教.隐形独角兽教.绝地教都是常见的信仰.为了方便,我们 ...
- tomcat源码分析(三)一次http请求的旅行-从Socket说起
p { margin-bottom: 0.25cm; line-height: 120% } tomcat源码分析(三)一次http请求的旅行 在http请求旅行之前,我们先来准备下我们所需要的工具. ...
- 11.14 T2 小x的旅行(小x的旅行)
1.小x的旅行 (travel.pas/c/cpp) [问题描述] 小x大学毕业后,进入了某个公司做了高层管理,他每年的任务就是检查这个公司在全国各地N个分公司的各种状况,每个公司都要检查一遍,且 ...
- hdoj 2066 一个人的旅行
Problem Description 虽然草儿是个路痴(就是在杭电待了一年多,居然还会在校园里迷路的人,汗~),但是草儿仍然很喜欢旅行,因为在旅途中 会遇见很多人(白马王子,^0^),很多事,还能丰 ...
随机推荐
- HTML基础part1
HTML基础 Web的本质就是利用浏览器访问socket服务端,socket服务端收到请求回复数据提供给浏览器进行渲染显示. import socket def main(): sock = sock ...
- Java设计模式(16)——行为模式之模板方法模式(Template)
一.概念 概念 UML简图 角色 使用场景 其实我们常用得抽象类就是这个模式得运用,所以基本上属于比较好理解的一种模式. 二.实践 根据上述角色,给出相应代码 抽象模板 /** * 抽象模板 * * ...
- 杭州优步uber司机第三组奖励政策
-8月9日更新- 优步杭州第三组: 定义为激活时间在2015/8/3之后(含)的车主(以优步后台数据显示为准) 滴滴快车单单2.5倍,注册地址:http://www.udache.com/如何注册Ub ...
- cakephp中find('list')的使用
运用一.快速实现下拉菜单 控制器中,使用find('list')返回的是键值对的数组,键名是array的第一个参数id,键值就是第二个参数content. public function list_s ...
- 聊聊WS-Federation(test)
本文来自网易云社区 单点登录(Single Sign On),简称为 SSO,目前已经被大家所熟知.简单的说, 就是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. 举例: 我们 ...
- Appium1.8及以上命令行启动
安装命令行启动版本的Appium,appium-doctor需要独立下载了,用 npm的话需要FQ才好使,所有安装了cnpm代替npm, cnpm是从淘宝的国内镜像下载 npm config rm p ...
- SpriteKit手机游戏摇杆JoyStick的使用 -- by iFIERO游戏开发教程
### 工欲善其事,必先利其器 有时候学习如何应用第三方库是非常重要的,因为我们不用再自己重复造轮子,在这里,我们就把原先利用重力感应来操控飞机改为用游戏摇杆joystick来操控,具体的操作如下:` ...
- (C#)原型模式—深复制与浅复制
1.原型模式 用原型实例指定创建对象的实例,并且通过拷贝这些原型创建新的对象. *原型模式隐藏了创建对象的细节,提高了性能. *浅复制:被复制对象的所有变量都含有与原来对象相同的值,而且所有对其他对象 ...
- 了解Python控制流语句——for 循环
for 循环 Python教程中for...in 语句是另一种循环语句,其特点是会在一系列对象上进行迭代(Iterates),意即它会遍历序列中的每一个项目.我们将在后面的Python序列(Seque ...
- Java Web开发框架Spring+Hibernate整合效果介绍(附源码)(已过期,有更好的)
最近花了一些时间整合了一个SpringMVC+springAOP+spring security+Hibernate的一套框架,之前只专注于.NET的软件架构设计,并没有接触过Java EE,好在有经 ...