7032: Knightsbridge Rises(网络流+dfs)
Knightsbridge Rises
时间限制: 1 Sec 内存限制: 128 MB Special Judge提交: 46 解决: 13
[提交] [状态] [讨论版] [命题人:admin]
题目描述
High-rise buildings in the wealthy retail district of Knightsbridge are usually built with exotic hoisting machines known, in construction circles, as cranes.
While it is common to mount these devices on the ground, it’s not always ideal—for example, a skyscraper building would need an equally tall crane. In these cases, the clever solution the industry has developed is for a smaller crane to be mounted directly on top of the tower.
However, this solution presents another challenge: how can such heavy equipment be brought to the summit in the first place? The industry’s solution is to simply use a smaller crane to lift the main crane up. And if that smaller crane is still too massive, find another smaller still, and so on, until said device fits inside a pocket and can be carried up by some enterprising engineer.
Once on top of the building, whether by being carried up, or by being lifted up by another crane capable of holding its weight, a crane can be used to lift others up onto its tower. Once raised, it is not possible to transfer a crane anywhere else.
We have several construction projects in progress at the moment, each with its own requirements on how heavy the loads eventually lifted from the ground need to be. Find an assignment of cranes to buildings that can satisfy these requirements.
While it is common to mount these devices on the ground, it’s not always ideal—for example, a skyscraper building would need an equally tall crane. In these cases, the clever solution the industry has developed is for a smaller crane to be mounted directly on top of the tower.
However, this solution presents another challenge: how can such heavy equipment be brought to the summit in the first place? The industry’s solution is to simply use a smaller crane to lift the main crane up. And if that smaller crane is still too massive, find another smaller still, and so on, until said device fits inside a pocket and can be carried up by some enterprising engineer.
Once on top of the building, whether by being carried up, or by being lifted up by another crane capable of holding its weight, a crane can be used to lift others up onto its tower. Once raised, it is not possible to transfer a crane anywhere else.
We have several construction projects in progress at the moment, each with its own requirements on how heavy the loads eventually lifted from the ground need to be. Find an assignment of cranes to buildings that can satisfy these requirements.
输入
• One line containing an integer N (1 ≤ N ≤ 100), the number of types of cranes under our command.
• N further lines, each containing a pair of space-separated integers Wi and Li (0 ≤Wi, Li ≤ 106), the weight and maximum lifting weight of the i-th crane in kilograms.
• One line containing an integer M (1 ≤ M ≤ 100), the number of tower blocks.
• One line containing the M space-separated integers Ti (1 ≤ Ti ≤ 106), Ti being the weight we need to be able to lift from the top of the i-th building by the end.
• N further lines, each containing a pair of space-separated integers Wi and Li (0 ≤Wi, Li ≤ 106), the weight and maximum lifting weight of the i-th crane in kilograms.
• One line containing an integer M (1 ≤ M ≤ 100), the number of tower blocks.
• One line containing the M space-separated integers Ti (1 ≤ Ti ≤ 106), Ti being the weight we need to be able to lift from the top of the i-th building by the end.
输出
If it is not possible to supply all of the buildings, output impossible.
Otherwise, output M lines. The i-th line should contain a list of space-separated integers x1...xk (1 ≤ x ≤ N ), describing the order in which cranes should be raised onto the i-th building from the input.
Otherwise, output M lines. The i-th line should contain a list of space-separated integers x1...xk (1 ≤ x ≤ N ), describing the order in which cranes should be raised onto the i-th building from the input.
样例输入
5
0 1
1 2
2 3
3 4
0 2
2
4 2
样例输出
5 3 4
1 2
来源/分类
思路:
网络流裸题+保存路径。
n 个起重机有 l , r 。
建图:
拆点建边。
起点与 l[i]=0的起重机建边。
自身与自身建边。
第 i 个起重机与其他l[j] <=r[i]的点建边。
m个楼房与汇点建边。
边权都为1。
保留路径,就这个题而言,当某个起重机被选择时,该边剩余流量为0。 dfs搜一下就可以。(该题有spj)
代码如下:
#include <bits/stdc++.h> using namespace std; const int maxn=1e3+10; const int inf=0x3f3f3f3f; struct Edge{ int u,v,cap,flow; }; struct Dinic{ int s,t; vector<Edge>edges; vector<int>head[maxn]; int dis[maxn],cur[maxn]; bool vis[maxn]; inline void init(int n){ for (int i=0; i<=n+1; i++) head[i].clear(); edges.clear(); } inline void add(int u,int v,int w){ edges.push_back(Edge{u,v,w,0}); edges.push_back(Edge{v,u,0,0}); int cnt=edges.size(); head[u].push_back(cnt-2); head[v].push_back(cnt-1); } bool bfs(){ memset(vis,false,sizeof(vis)); queue<int>q; q.push(s); dis[s]=0,vis[s]=1; while(!q.empty()){ int u=q.front();q.pop(); for (int i=0; i<head[u].size(); i++){ Edge e=edges[head[u][i]]; if(!vis[e.v] && e.cap>e.flow){ vis[e.v]=1; q.push(e.v); dis[e.v]=dis[u]+1; } } } // puts("-1"); return vis[t]; } int dfs(int x,int cap){ if(x==t || cap==0) return cap; int flow=0,f; for (int &i=cur[x]; i<head[x].size(); i++){ cur[x]=i; Edge &e=edges[head[x][i]]; if(dis[e.v]==dis[x]+1 && (f=dfs(e.v,min(cap,e.cap-e.flow)))){ e.flow+=f; edges[head[x][i]^1].flow-=f; flow+=f; cap-=f; if(cap==0) break; } } return flow; } int Maxflow(int s,int t){ this->s=s; this->t=t; int flow=0; while(bfs()){ memset(cur,0,sizeof(cur)); flow+=dfs(s,inf); } return flow; } }dc; int n,m,l[maxn],r[maxn],w[maxn],tar; bool vis[maxn]; vector<int>ans[maxn],vec; void dfs(int u){ if(u>2*n) tar=u; if(tar==u) return; vec.push_back(u); vis[u]=1; for (int i=0; i<dc.head[u].size(); i++){ Edge e=dc.edges[dc.head[u][i]]; int v=e.v,f=e.cap-e.flow; if(dc.head[u][i]%2==0 && !vis[v] &&!f){ dfs(v); break; } } } int main(){ scanf("%d",&n); dc.init(n); for (int i=1; i<=n; i++) scanf("%d%d",&l[i],&r[i]); scanf("%d",&m); for (int i=1; i<=m; i++) scanf("%d",&w[i]); int s=0,t=n*2+m+1; for (int i=1; i<=m; i++) dc.add(2*n+i,t,1); for (int i=1; i<=n; i++) { if(l[i]==0) dc.add(s,i,1); for (int j=1; j<=n; j++){ if(i==j) dc.add(i,i+n,1); else if(r[i]>=l[j]) dc.add(i+n,j,1); } for (int j=1; j<=m; j++) if(r[i]>=w[j]) dc.add(i+n,j+2*n,1); } int d=dc.Maxflow(s,t); if(d!=m) return puts("impossible"),0; memset(vis,0,sizeof(vis)); for (int i=0; i<dc.head[s].size(); i++){ Edge e=dc.edges[dc.head[s][i]]; int v=e.v,f=e.cap-e.flow; if(!vis[v] && !f){ tar=0; vec.clear(); dfs(v); for (int i=0; i<vec.size(); i+=2) ans[tar-2*n].push_back(vec[i]); } } for (int i=1; i<=m; i++){ for (auto u:ans[i]) printf("%d ",u); printf("\n"); } return 0; }