NC22811. Happy new semester
描述
新学期开始了,大活一楼又堆起了山一样高的教材,而这学期学校特地推出了送书服务,不需要自己去买,直接在易班APP上下单就会有人把教材送到寝室楼一楼。
这个服务让学生们雀跃不已,但是可让负责管理教材运输的老师发了愁,每个运输工的力气都是有限的,怎么样才能最大效率的运送教材呢,于是他盯上了正在比赛的小西小理,打算让他们比赛设计出最好的运输方案,于是你作为小西的专属小抄,这个任务自然又落到了你的头上。
现在有力气值为c的一批运输工,整个学校中有n-1个宿舍楼需要运书。大活的编号为0,宿舍楼的编号为1~n-1。一共有m条可供选择的路线,其中第i条路线从Ui到Vi,最多运输的教材为Wi,消耗的力气值为Ci。每个宿舍楼只能从一个地方接收教材,但可以往多个宿舍楼运送教材。为了最大化每个运输工的作用,你的任务是设计出一个运送方案使路线中最小的教材运输量最大。
输入描述
输入第一行为数据组数T(T<=50)。每组数据第一行为3个整数n,m,c(1<=n<=60,1<=m<=10000,1<=c<=1e9)。
以下m行每行有4个整数Ui,Vi,Wi,Ci(0<=Ui,Vi<n,1<=Wi,Ci<=1e6,Ui!=Vi)描述一条运输线路。
输出描述
对每组数据,输出最小运煤量的最大值。若无法搭建网络,则输出“NO”(不含引号),输出占一行。
示例1
输入:
2 2 2 1 0 1 2 1 0 1 1 1 3 4 300 0 1 128 100 1 2 256 200 2 1 256 200 0 2 512 300
输出:
2 128
C++11(clang++ 3.9) 解法, 执行用时: 22ms, 内存消耗: 464K, 提交时间: 2020-03-17 14:49:13
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<math.h> using namespace std; const int INF=100000000; const int MAXN=1010; const int MAXM=1010000; #define ll int struct Edge { int u,v; ll cost; }edge[MAXM]; int pre[MAXN],id[MAXN],visit[MAXN],edgenum; void addedge(int u,int v,int cost) { Edge E={u,v,cost}; edge[edgenum++]=E; } ll in[MAXN]; ll zhuliu(int root,int n,int m,Edge edge[],int c) { int u,v; ll res=0; while(1) { for(int i=0;i<n;i++) in[i]=INF; for(int i=0;i<m;i++) if(edge[i].u!=edge[i].v&&edge[i].cost<in[edge[i].v]) { pre[edge[i].v]=edge[i].u; in[edge[i].v]=edge[i].cost; } for(int i=0;i<n;i++) if(i!=root&&in[i]==INF) return -1; int tn=0; memset(id,-1,sizeof(id)); memset(visit,-1,sizeof(visit)); in[root]=0; for(int i=0;i<n;i++) { res+=in[i]; if(res>c) return -1; v=i; while(visit[v]!=i&&id[v]==-1&&v!=root) { visit[v]=i; v=pre[v]; } if(v!=root&&id[v]==-1) { for(int u=pre[v];u!=v;u=pre[u]) id[u]=tn; id[v]=tn++; } } if(tn==0) break; for(int i=0;i<n;i++) if(id[i]==-1) id[i]=tn++; for(int i=0;i<m;) { v=edge[i].v; edge[i].u=id[edge[i].u]; edge[i].v=id[edge[i].v]; if(edge[i].u!=edge[i].v) edge[i++].cost-=in[v]; else swap(edge[i],edge[--m]); } n=tn; root=id[root]; } return res; } void init() { edgenum=0; } struct node { ll u,v,bit,cost; }E[MAXM]; int n,m,c; bool ok(int x) { init(); for(int i=0;i<m;i++) if(E[i].bit>=x) addedge(E[i].u,E[i].v,E[i].cost); int ans=zhuliu(0,n,edgenum,edge,c); return ans<=c&&ans!=-1; } int main() { int T,i; scanf("%d",&T); while(T--) { scanf("%d %d %d",&n,&m,&c); for(i=0;i<m;i++) scanf("%d %d %d %d",&E[i].u,&E[i].v,&E[i].bit,&E[i].cost); int l=1,r=1000000; int ans=0; while(l<=r) { int mid=(l+r)>>1; if(ok(mid)) l=mid+1,ans=max(ans,mid); else r=mid-1; } ans==0?puts("NO"):printf("%d\n",ans); } return 0; }