题意:
n个点,m个边,两两之间可以到达
我们要运送货物,如果量是x,运送第一天是x,第二天是x,第n天是x,运送几天取决于起点和终点的长度,长度=运送天数,问现在预算是budget,从s到t最多能运多少货物?
题解:
脑残了。。n<100,我们肯定要先求出任意两点的最短距离,还用什么spfa,什么地杰斯特拉,直接floyed不香吗
预算是budget,货物是x,天数(路径长)为len
当budget>x^1+x^2+...x^len=x*(1-x)/(1-x)
现在知道budget,知道len,求x的最大情况,那直接二分不就OK了
emmm。。。好简单,比赛时为什么没做出来。。。
代码:
/* 3 2 1 2 2 3 2 1 3 5 2 3 2 */ #include<bits/stdc++.h> using namespace std; #define ll long long const int maxn=200; ll dis[maxn][maxn]; ll budget,len; bool check(int x) { ll sum=0,r=1; for(int i=1;i<=len;i++) { r*=x; sum+=r; if(sum>budget)return 0; } // sum=pow(x,len); if(sum<=budget)return 1; else return 0; } int main(){ int n,m; cin>>n>>m; memset(dis, 0x3f3f3f3f, sizeof(dis)); for(int i=1;i<=m;i++) { int x,y; cin>>x>>y; dis[x][y]=1; dis[y][x]=1; } for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) { for(int k=1;k<=n;k++) { if(dis[i][j]>dis[i][k]+dis[k][j]) dis[i][j]=dis[i][k]+dis[k][j]; dis[j][i]=dis[i][j]; } } } int t; cin>>t; while(t--) { int u,v; cin>>u>>v>>budget; len=dis[u][v]; ll l=0,r=budget; while(l<r) { ll mid=(l+r+1)>>1; if(check(mid))l=mid; else r=mid-1; } cout<<l<<endl; } } /* 5 1 2 1 2 3 */