OJ题号:
BZOJ1070、洛谷2053
思路:
最初的爆零解法:
每个工人向$S$连一条容量为$inf$、费用为$0$的边,(每个工人可以修很多车) 每个工人向每辆车连一条容量为$1$,费用等于题目描述的边,(一个工人只能修一次同一辆车) 每辆车向$T$连一条容量为$1$,费用为$0$的边。(每辆车总共只能修一次) 每次增广以后将$S$到该工人之间的费用增加修理该车所用的时间,然后不停重复。 正确解法: 把每个工人拆成$n$个点,向每辆车连一条边,边权依次增加,表示该工人的第$i$个点表示第$i$次修理车所花的费用。 其余边与我错误的解法相同。 最后跑一遍最小费用最大流即可。1 #include2 #include 3 #include 4 #include 5 #include 6 inline int getint() { 7 char ch; 8 while(!isdigit(ch=getchar())); 9 int x=ch^'0';10 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');11 return x;12 }13 const int inf=0x7fffffff;14 int s,t;15 struct Edge {16 int from,to,remain,cost;17 };18 const int E=100000,V=800;19 Edge e[E];20 std::vector g[V];21 int sz=0;22 inline void add_edge(const int u,const int v,const int w,const int c) {23 e[sz]=(Edge){u,v,w,c};24 g[u].push_back(sz);25 sz++;26 }27 int p[V],d[V],a[V];28 bool inq[V];29 inline void Augment() {30 memset(a,0,sizeof a);31 a[s]=inf;32 std::queue q;33 q.push(s);34 memset(inq,0,sizeof inq);35 inq[s]=true;36 d[s]=0;37 for(int i=1;i<=t;i++) d[i]=inf;38 while(!q.empty()) {39 int x=q.front();40 q.pop();41 inq[x]=false;42 for(unsigned i=0;i