前话:因为多组没有初始化 c n t cnt cnt边的数量,导致一直超时,懵逼了,对于多组数据重建图时,只需要初始化 c n t cnt cnt和 h [ ] h[] h[]数组 ( h e a d [ ] ) (head[]) (head[])即可。
题意:给定 ( n , m ) (n,m) (n,m)无向图, m m m条带权有向边(费用已知容量未知),给 q q q次询问,每次询问给出 u , v , ( u ≤ v ) u,v,(u\leq v) u,v,(u≤v),问在所有边容量为 u v \dfrac{u}{v} vu下,总流量为 1 1 1的最小费用。
思路: M C M F + MCMF+ MCMF+贪心。
设 c o s t ( x , y ) 为 cost(x,y)为 cost(x,y)为在所有边容量为 x x x下,总流量为 y y y的最小费用。
考虑先跑一边 M C M F MCMF MCMF,求出在所有边容量为 1 1 1下的所有增广路。
则题意变为求 c o s t ( u v , 1 ) cost(\dfrac{u}{v},1) cost(vu,1)。
因为所有边容量一样,所以 c o s t = ∑ 增 广 路 个 数 c n t c n t f l o w [ e n d ] × d i s [ e n d ] = c a p a c i t y × ∑ 增 广 路 个 数 c n t c n t d i s [ e n d ] cost=\sum\limits_{增广路个数cnt}^{cnt} flow[end]\times dis[end]=capacity\times\sum\limits_{增广路个数cnt}^{cnt}dis[end] cost=增广路个数cnt∑cntflow[end]×dis[end]=capacity×增广路个数cnt∑cntdis[end]。
即 c o s t cost cost与 c a p a c i t y capacity capacity成线性关系。
所以有 c o s t ( u v , 1 ) = c o s t ( u , v ) v cost(\dfrac{u}{v},1)=\dfrac{cost(u,v)}{v} cost(vu,1)=vcost(u,v)。
且设 c a p a c i t y = 1 capacity=1 capacity=1对应的最大流为 m a x f l o w maxflow maxflow,
则 c a p a c t i y = u capactiy=u capactiy=u对应的最大流也是线性关系为 m a x f l o w × u maxflow\times u maxflow×u。
所以我们先考虑特判不成立的情况。
即 1 : v = 0 1:v=0 1:v=0,分母显然不能为0.
2 : m a x f l o w × u < v 2:maxflow\times u
接下我们考虑怎么构造答案。
我们需要构造出一个总流量为 v v v的方案,而每条增广路的流量贡献为 u u u。
所以我们设 v = a × u + b v=a\times u+b v=a×u+b。
表示我们需要 a a a条增广路和一条流量只需要 b b b的增广路。
之前我们已经求出了 c o s t ( 1 , m a x f l o w ) cost(1,maxflow) cost(1,maxflow)的所有增广路,因为 M C M F MCMF MCMF求增广路的顺序就是由最小费用到最大费用的,所以我们直接根据贪心思想取前 a a a条,和第 a + 1 a+1 a+1条作为 b b b。
这样 c o s t ( u , v ) = a × ∑ i = 1 a a u g [ i ] + b × a u g [ a + 1 ] cost(u,v)=a\times \sum_{i=1}^a aug[i]+b\times aug[a+1] cost(u,v)=a×∑i=1aaug[i]+b×aug[a+1]。
a u g [ i ] aug[i] aug[i]表示第 i i i条增广路的费用。
则最终答案为: c o s t ( u , v ) v \dfrac{cost(u,v)}{v} vcost(u,v),约分一下即可。
#include
using namespace std;
typedef long long ll;
const int N=105,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a) memset(a,0,sizeof a)
#define fmst(a) memset(a,0x7f,sizeof a)
#define lx x<<1
#define rx x<<1|1
#define reg register
#define PII pair
#define fi first
#define se second
#define pb push_back
int cnt=1,h[N],flow[N],dis[N],vis[N],n,m,s,t,ans[N],tot;
queue<int>q;
struct edge{
int to,nt,f,w;//f:flow ,w:cost
}e[N<<1];
int pre[N];
void add(int u,int v,int f,int w){
e[++cnt]={v,h[u],f,w},h[u]=cnt;
}
bool spfa(){// 跑spfa
fmst(dis),fmst(flow),mst(vis); //初始化.
q.push(s),dis[s]=0,vis[s]=1,pre[t]=-1;//预处理
while(!q.empty()){
int u=q.front();q.pop();vis[u]=0;
for(int i=h[u];i;i=e[i].nt){
int v=e[i].to,f=e[i].f,w=e[i].w;
if(f>0&&dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
pre[v]=i;
flow[v]=min(flow[u],f);
if(!vis[v]) vis[v]=1,q.push(v);
}
}
}
return pre[t]!=-1;
}
void MCMF(){ //MIncost Maxflow
while(spfa()){
int u=t,x=flow[t];
ans[++tot]=dis[u];
while(u!=s){
e[pre[u]].f-=x;
e[pre[u]^1].f+=x;
u=e[pre[u]^1].to;
}
}
for(int i=1;i<tot;i++) ans[i+1]+=ans[i];
}
ll gcd(ll a,ll b){
return b==0?a:gcd(b,a%b);
}
int main(){
while(~scanf("%d%d",&n,&m)){
s=1,t=n,tot=0,cnt=1;
mst(h);
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,1,w),add(v,u,0,-w);
}
MCMF();
int q;
scanf("%d",&q);
while(q--){
int u,v;
scanf("%d%d",&u,&v);
if((!v)||1LL*tot*u<v) puts("NaN");
else {
int a=v/u,b=v%u;
ll fz=1LL*ans[a]*u+1LL*b*(ans[a+1]-ans[a]);
ll g=gcd(fz,v);
printf("%lld/%lld\n",fz/g,v/g);
}
}
}
return 0;
}