首先要发现起点相同的情况下,到其他点的最优路径也是相同的
所以就变成了求起点到n1个点的最优路径,
最优的方案是走过的边v1和/v2和最小
分数规划的标准形式
然后就可以二分+spfa(二分区间是0到10,因为最差情况是1+1+1/10+10+10=1/10和10+10+10/1+1+1=10)
然后无解就是二分出界也没办法得到值,起点到他的花费就设为inf
然后第二问是加权最小边覆盖问题,是np,,但他是二分图,所以就变成了边要么是属于左端点,要么是属于右端点,就是最大权闭合子图(最小割)
注:spfa要提前剪枝,不然会被卡
码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
#define inf 1000000009
#define N 300000
queue<int>q;
vector<int>V[N],Q[N],Z[N];
vector<double>T[N],S[N];
int a,b,t,s,yuan[N],zhong[N],tot=-1,n,m,hou[N],xia[N],m1,n1;
bool vis[N];
double l,r,v[N],ans[N],d[N];
void jian(int a,int b,double c)
{
++tot,hou[tot]=yuan[a],yuan[a]=tot;zhong[tot]=b,v[tot]=c;
}
void jia(int a,int b,double c)
{
jian(a,b,c);
jian(b,a,0);
}
double spfa(int t,double cc)
{
int i,j;
for(i=1;i<=n;i++)d[i]=-inf;
d[n]=0;
q.push(n);
while(!q.empty())
{
int st=q.front();
vis[st]=0;
q.pop();
for(i=0;i<V[st].size();i++)
{
int nd=V[st][i];
double k=cc*S[st][i]-T[st][i];
if(d[nd]<d[st]+k)
{
d[nd]=d[st]+k;
if(nd==t&&d[t]>0)return 1;
if(vis[nd]==0)
{
vis[nd]=1;q.push(nd);
}
}
}
}
return d[t];
}
bool bfs()
{
int i;
memset(d,0x7f,sizeof(d));
for(i=1;i<=t;i++)
xia[i]=yuan[i];
d[s]=0;
q.push(s);
while(!q.empty())
{
int st=q.front();
q.pop();
for(i=xia[st];i!=-1;i=hou[i])
{
int nd=zhong[i];
if(fabs(v[i]-0)<=0.000001||d[nd]<inf)continue;
d[nd]=d[st]+1;
q.push(nd);
}
}
return d[t]<inf;
}
double dfs(int o,int t,double limit)
{
if(!limit||o==t)return limit;
int i;
double f,flow=0;
for(i=xia[o];i!=-1;i=hou[i])
{
xia[o]=i;
int nd=zhong[i];
if(d[nd]==d[o]+1&&fabs((f=dfs(nd,t,min(limit,v[i])))-0)>0.000001)
{
flow+=f;
limit-=f;
v[i]-=f;
v[i^1]+=f;
if(fabs(limit-0)<=0.000001)break;
}
}
return flow;
}
double dinic()
{
double daan=0;
while(bfs())
{
daan+=dfs(s,t,inf);
}
return daan;
}
int main()
{
memset(yuan,-1,sizeof(yuan));
scanf("%d%d",&n,&m);
int i;
double l1,l2;
for(i=1;i<=m;i++)
{
scanf("%d%d%lf%lf",&a,&b,&l1,&l2);
V[a].push_back(b);
T[a].push_back(l1);
S[a].push_back(l2);
}
scanf("%d%d",&m1,&n1);
for(i=1;i<=n1;i++)
{
l=0;r=12;
while(l+0.00000001<r)
{
double mid=(l+r)/2;
if(spfa(i,mid)<0)
{
l=mid+0.000001;
}else r=mid;
}
ans[i]=l;
if(l>11)ans[i]=inf;
}
tot=-1;
for(i=1;i<=m1;i++)
{
scanf("%d%d",&a,&b);
jia(a,b,inf);
}
s=n1+1;
t=n1+2;
for(i=1;i<=n1;i++)
{
if(i%2)
{
jia(s,i,ans[i]);
}else
{
jia(i,t,ans[i]);
}
}
double daan=dinic();
if(daan+0.00000001>=inf)printf("-1");
else printf("%.1lf",daan);
}