思路: 二分 bit 跑最小树形图是否满足花费的情况。
代码 :
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N =65;
const int M =2e4+5;
const ll inf =1e18+5;
ll in[N];
int vis[N],id[N],pre[N];
struct Edge
{
int u,v,f;
ll b;
ll c;
}edge[M],edges[M];
// kuangbin 板子
ll zhuliu(int root,int n,int m)
{
ll res=0,u,v;
while(1)
{
for(int i=0;i<n;i++) in[i]=inf;
for(int i=0;i<m;i++){
if(edges[i].u!=edges[i].v&&edges[i].c<in[edges[i].v])
{
in[edges[i].v]=edges[i].c;
pre[edges[i].v]=edges[i].u;
}
}
for(int i=0;i<n;i++){
if(root!=i&&in[i]==inf) return -1;
}
int cnt=0;
memset(id,-1,sizeof(id));
memset(vis,-1,sizeof(vis));
in[root]=0;
for(int i=0;i<n;i++)
{
res+=in[i];
v=i;
while(vis[v]!=i&&id[v]==-1&&v!=root)
{
vis[v]=i;
v=pre[v];
}
if(v!=root&&id[v]==-1){
for(u=pre[v];u!=v;u=pre[u]) id[u]=cnt;
id[v]=cnt++;
}
}
if(cnt==0) break;
for(int i=0;i<n;i++){
if(id[i]==-1) id[i]=cnt++;
}
for(int i=0;i<m;)
{
v=edges[i].v;
edges[i].u=id[edges[i].u]; edges[i].v=id[edges[i].v];
if(edges[i].u!=edges[i].v)
{
edges[i++].c-=in[v];
}
else swap(edges[i],edges[--m]);
}
n=cnt;
root=id[root];
}
return res;
}
int n,m,C;
int B[M];
int jud(ll num)
{
int tot=0;
for(int i=0;i<m;i++)
{
if(edge[i].b>=num)edges[tot++]=edge[i];
}
ll ans=zhuliu(0,n,tot);
//cout<<"ans "<<ans<<endl;
if(ans==-1) return 0;
if(ans>C) return 0;
return 1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d %d %d",&n,&m,&C);
for(int i=0;i<m;i++){
scanf("%d %d %lld %lld",&edge[i].u,&edge[i].v,&edge[i].b,&edge[i].c);
B[i]=edge[i].b;
}
sort(B,B+m);
int tot=unique(B,B+m)-B;
int l,r,mid;
l=0; r=tot-1;
ll ans=-1;
while(l<=r)
{
mid=(l+r)>>1;
//cout<<"mid "<<mid<<endl;
if(jud(B[mid])){
ans=B[mid];
l=mid+1;
}
else r=mid-1;
}
if(ans==-1)
{
printf("streaming not possible.\n");
}
else printf("%lld kbps\n",ans);
}
return 0;
}