[SDOI2011]保密

Posted by Dispwnl on April 26, 2019

题目

题解

感觉就是道多合一……

先处理出来$n$到$1…n1$的最短距离,即求$\frac{\sum_{j\in path(n,i)}t_j}{\sum_{j\in path(n,i)}s_j}$最大,一脸分数规划的样子,设二分的答案为$T$,则有$\sum_{j\in path(n,i)}t_j -T\times \sum_{j\in path(n,i)}s_j\le 0$

即$\sum_{j\in path(n,i)}t_j -T\times s_j\le 0$,把每条边赋值成$t-T\times s$,求$n$到$i$的最短路即可,因为这个图是个$DAG$,直接拓扑排序处理

处理完之后要求和的最小值,一脸最小割的样子,$u$连$v\inf$边,然后$S$连奇数点,偶数点连$T$,跑个网络流即可

代码

# include<iostream>
# include<cstring>
# include<cstdio>
# include<algorithm>
using namespace std;
const int MAX=1e5+5,inf=1e8;
const double fs=1e-6;
struct p{
	int x,y;
	double d;
}c[MAX];
int n,m,n1,m1,num=1,T;
int d[MAX],H[MAX],qu[MAX],h[MAX];
double Ans;
double ans[MAX];
bool use[MAX];
int read()
{
	int x(0);
	char ch=getchar();
	for(;!isdigit(ch);ch=getchar());
	for(;isdigit(ch);x=x*10+ch-48,ch=getchar());
	return x;
}
struct Top{
	struct p{
		int x,y,s,t;
	}c[MAX];
	int num;
	int h[MAX],Du[MAX],du[MAX],qu[MAX];
	double f[MAX];
	void add(int x,int y,int s,int t) {++Du[y],c[++num]=(p){h[x],y,s,t},h[x]=num;}
	bool look(double mid,int x)
	{
		int hl=1,tl=0;
		for(int i=1;i<=n;++i)
		  du[i]=Du[i],f[i]=inf,!du[i]?qu[++tl]=i:0;
		f[n]=0;
		while(hl<=tl)
		{
			int tt=qu[hl++];
			if(tt==x) return f[x]<=fs;
			for(int i=h[tt],y;i;i=c[i].x)
			  {
			  	y=c[i].y,f[y]=min(f[y],f[tt]+c[i].t-mid*c[i].s);
			  	if(!--du[y]) qu[++tl]=y;
			  }
		}
		return f[x]<=fs;
	}
	double Solve(int x)
	{
		double l=0,r=10*m,ans=inf;
		while(l<=r)
		{
			double mid=(l+r)/2;
			if(look(mid,x)) ans=mid,r=mid-fs;
			else l=mid+fs;
		}
		return ans;
	}
	void Solve()
	{
		for(int i=1,a,b,s,t;i<=m;++i)
		  a=read(),b=read(),t=read(),s=read(),add(a,b,s,t);
		m1=read(),n1=read();
		for(int i=1;i<=n1;++i)
		  ans[i]=Solve(i);
	}
}A;
void add(int x,int y,double d)
{
	c[++num]=(p){h[x],y,d},h[x]=num;
	c[++num]=(p){h[y],x,0},h[y]=num;
}
bool bfs()
{
	memset(d,0,sizeof(d));
	int hl=1,tl=d[0]=1;
	while(hl<=tl)
	{
		int tt=qu[hl++];
		for(int i=h[tt],y;i;i=c[i].x)
		  if(c[i].d>fs&&!d[y=c[i].y])
		  {
		  	d[y]=d[tt]+1,qu[++tl]=y;
		  	if(y==T) return 1;
		  }
	}
	return 0;
}
double dfs(int x=0,double dix=inf)
{
	if(x==T||dix<=fs) return dix;
	double sum=0;
	for(int &i=H[x],y;i;i=c[i].x)
	  if(c[i].d>fs&&d[y=c[i].y])
	  {
	  	double dis=dfs(y,min(dix,c[i].d));
	  	if(dis>fs)
	  	{
	  		sum+=dis,dix-=dis,c[i].d-=dis,c[i^1].d+=dis;
	  		if(dix<=fs) break;
		}
	  }
	if(sum<=fs) d[x]=-2;
	return sum;
}
double Dinic()
{
	double tot=0,D;
	while(bfs())
	{
		memcpy(H,h,sizeof(h));
		while(D=dfs()) tot+=D;
	}
	return tot;
}
int main()
{
	n=read(),m=read(),A.Solve(),T=n1+1;
	for(int i=1;i<=n1;++i)
	  i&1?add(0,i,ans[i]):add(i,T,ans[i]);
	for(int i=1,u,v;i<=m1;++i)
	  u=read(),v=read(),add(u,v,inf);
	Ans=Dinic();
	if(Ans>inf) return printf("-1"),0;
	return printf("%.1lf",Ans),0;
}