01分数规划+最大权闭合子图
倒拓扑序处理每个节点
f[x]=∑f[v]n+1
二分答案 val
只需要判断是否存在
∑f[v]+1−val>0
即可
点权下放给边,限制{x,y}即为若边x存在,则边y存在
建图,跑网络流即可
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<vector>
#define inf 0x7fffffff
#define eps 1e-7
using namespace std;
namespace network{
const int N = 1005;
const int S = 1001;
const int T = 1002;
int e=2,head[N];
struct edge{
int u,v,next;
double f;
}ed[310000];
void add(int u,int v,double f){
ed[e].u=u;ed[e].v=v;ed[e].f=f;
ed[e].next=head[u];head[u]=e++;
ed[e].u=v;ed[e].v=u;ed[e].f=0;
ed[e].next=head[v];head[v]=e++;
}
int dep[N];
int q[N],h,t;
bool bfs(){
memset(dep,-1,sizeof dep);
dep[S]=1; h=t=1; q[1]=S;
while(h<=t){
int x=q[h++];
for(int i=head[x];i;i=ed[i].next){
if(ed[i].f&&dep[ed[i].v]==-1){
dep[ed[i].v]=dep[x]+1;
q[++t]=ed[i].v;
}
}
}
return dep[T]!=-1;
}
double dfs(int x,double f){
if(x==T||f==0)return f;
double ans=0;
for(int i=head[x];i;i=ed[i].next){
if(ed[i].f&&dep[ed[i].v]==dep[x]+1){
double nxt=dfs(ed[i].v,min(f,ed[i].f));
ed[i].f-=nxt; ed[i^1].f+=nxt;
f-=nxt; ans+=nxt;
if(f==0)break;
}
}
if(ans==0)dep[x]=-1;
return ans;
}
double dinic(){
double ans=0;
while(bfs())ans+=dfs(S,inf);
return ans;
}
void init(){memset(head,0,sizeof head);e=2;}
}
namespace graph{
const int N =505;
int e=1,head[N],out[N];
vector<int> lim[N];
bool vis[N];
double f[N];
struct edge{
int u,v,next;
}ed[2*N];
void add(int u,int v){
ed[e].u=u;ed[e].v=v;
ed[e].next=head[u];
head[u]=e++;out[u]++;
}
bool check(int x,double y){
network::init();
double sum=0;
for(int i=head[x];i;i=ed[i].next){
int v=ed[i].v;
double val=f[v]+1-y;
sum+=max(val,(double)0);
if(val>0)network::add(network::S,i,val);
else network::add(i,network::T,-val);
for(int j=0;j<lim[i].size();j++)
network::add(i,lim[i][j],(double)inf);
}
return sum-network::dinic()>0;
}
double solve(int x){
if(!out[x])return 0.0;
double l=0,r=0,mid,ans;
for(int i=head[x];i;i=ed[i].next)
r=max(r,f[ed[i].v]+1);
while(r-l>=eps){
mid=(l+r)/2.0;
if(check(x,mid))l=ans=mid;
else r=mid;
}
return ans;
}
void work(int x){
for(int i=head[x];i;i=ed[i].next)
if(!vis[ed[i].v]){
work(ed[i].v);
vis[ed[i].v]=1;
}
f[x]=solve(x);
}
}
int main(){
int n,m,k;
scanf("%d%d%d",&n,&m,&k);
for(int i=1,u,v;i<=m;i++){
scanf("%d%d",&u,&v);
graph::add(u,v);
}
for(int i=1,x,y;i<=k;i++){
scanf("%d%d",&x,&y);
graph::lim[x].push_back(y);
}
graph::work(1);
printf("%lf\n",graph::f[1]);
}
/*
3 3 1
1 2
1 3
2 3
1 2
*/