您的位置:首页 > 其它

BZOJ4501 旅行

2016-06-15 22:12 155 查看
由于是一个DAG,我们可以拓扑序求f[x]表示以x为起点的最大期望长度,对于点x,用其所有出边向x转移其实就是选择一些出边保留,剩下的删掉,要你最大化


这是一个01分数规划问题,我们设上式>L,然后把所有东西移到不等式左边,就得到答案比L大的条件sigma (f[y]+1)- L*sigma 1>0

于是我们就要最大化左边,因为题目保证关联的边起点相同,所以每个点之间互不影响,我们发现y被删掉之后x也会被删掉相当于x被选的条件是y被选,所以用最大权闭合子图求就好了

#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<iomanip>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<bitset>
using namespace std;
#define MAXN 2010
#define MAXM 10010
#define ll long long
#define INF 1000000000
#define MOD 1000000007
#define eps 1e-10
struct vec{
int to;
int fro;
double v;
int num;
};
struct G{
vec mp[MAXM];
int tai[MAXN],cnt;
void init(){
memset(tai,0,sizeof(tai));
cnt=1;
}
inline void be(int x,int y,int z){
mp[++cnt].to=y;
mp[cnt].fro=tai[x];
tai[x]=cnt;
mp[cnt].num=z;
}
inline void be(int x,int y,double z){
mp[++cnt].to=y;
mp[cnt].fro=tai[x];
tai[x]=cnt;
mp[cnt].v=z;
}
inline void bse(int x,int y,double z){
be(x,y,z);
be(y,x,0.0);
}
void cal(int x);
bool OK(double x);
bool bfs();
double dfs(int x,double mx);
void build(int x);
double mf();
};
G g,fg;
int q[MAXN],hd,tl;
int d[MAXN];
int s=MAXN-1,t=MAXN-2;
double f[MAXN];
double ans;
bool vis[MAXN];
vector<int>dad[MAXN];
bool G::bfs(){
int i,x,y;
hd=tl=0;
memset(d,0,sizeof(d));
q[tl++]=s;
d[s]=1;
while(hd!=tl){
x=q[hd++];
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
if(!d[y]&&mp[i].v>eps){
d[y]=d[x]+1;
q[tl++]=y;
}
}
}
return d[t];
}
double G::dfs(int x,double mx){
int i,y;
if(x==t){
return mx;
}
double re=0,tmp;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
if(d[y]==d[x]+1&&mp[i].v>eps){
tmp=dfs(y,min(mx,mp[i].v));
mp[i].v-=tmp;
mp[i^1].v+=tmp;
mx-=tmp;
re+=tmp;
if(mx<eps){
return re;
}
}
}
if(re<eps){
d[x]=0;
}
return re;
}
double G::mf(){
double re=0;
while(bfs()){
re+=dfs(s,INF);
}
return re;
}
void G::build(int x){
int i;
for(i=0;i<dad[x].size();i++){
fg.bse(x,dad[x][i],1.0*INF);
}
}
void G::cal(int x){
if(vis[x]){
return ;
}
vis[x]=1;
int i,y;
double l=0,r=0;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
cal(y);
r=max(r,f[y]+1);
}
double ans=0;
while(fabs(l-r)>eps){
double mid=(l+r)/2;
fg.init();
ans=0;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
fg.build(mp[i].num);
if((f[y]+1)-mid<=0){
fg.bse(s,mp[i].num,mid-(f[y]+1));
}else{
fg.bse(mp[i].num,t,(f[y]+1)-mid);
ans+=(f[y]+1)-mid;
}
}
ans-=fg.mf();
if(ans>eps){
f[x]=mid;
l=mid;
}else{
r=mid;
}

}
}
int n,m,k;
int main(){
int i,x,y,z;
scanf("%d%d%d",&n,&m,&k);
for(i=1;i<=m;i++){
scanf("%d%d",&x,&y);
g.be(x,y,i);
}
for(i=1;i<=k;i++){
scanf("%d%d",&x,&y);
dad[y].push_back(x);
}
g.cal(1);
printf("%.2lf\n",f[1]);
return 0;
}

/*

*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: