(beginer) 网络流 UVA 10249 - The Grand Dinner
2014-02-08 09:55
866 查看
Problem D
The Grand Dinner
Input: standard input
Output:
standard output
Time Limit: 15 seconds
Memory Limit: 32 MB
Each team participating in this
year’s ACM World Finals contest is
expected to join the grand dinner to be arranged after the prize giving ceremony
ends. In order to maximize the interaction among the members of different teams,
it is expected that no two members of the same team sit at the same table.
Now, given the number of members
in each team (including contestants, coaches, reserves, guests etc.) and the
seating capacity of each available table, you are to determine whether it is
possible for the teams to sit as described in the previous paragraph. If such an
arrangement is possible you must also output one possible seating arrangement.
If there are multiple possible arrangements, any one is acceptable.
Input
The input file may contain multiple test cases. The
first line of each test case contains two integers M (1 ?
M ?
70) and N (1 ?
N ?
50) denoting the number of teams and the number of tables respectively. The
second line of the test case contains M integers where the i-th (1 ?
i ?
M) integer mi (1 ?
mi?
100) indicates the number of members of team i. The third line contains N integers where the j-th (1 ?
j ?
N) integer nj (2 ?
nj?
100) indicates the seating capacity of table j.
A test case containing two zeros
for M and N terminates the input.
Output
For each test case in the input
print a line containing either 1 or
0 depending on whether or not there
exists a valid seating arrangement of the team members. In case of a successful
arrangement print M additional lines where the i-th (1 ?
i ?
M) of these lines contains a table number (an integer from 1 to N) for each of the members of
team i.
Sample Input
4
5
4 5
3 5
3 5
2 6 4
4
5
4 5
3 5
3 5
2 6 3
0
0
Sample Output
1
1 2
4 5
1 2
3 4 5
2 4
5
1 2
3 4 5
0
(World Finals Warm-up Contest,
Problem Setter: Rezaul Alam Chowdhury)
代码:有个M个队伍,N个桌子,你要为这些人安排位子,不能有两个同队的人做在一张桌子上。问怎么安排。
思路:我们可以用网络流来做,有一个源点连向每一个桌子,容量为桌子的容量,桌子连向每一个队伍,容量为1,每个队伍连向一个汇点,容量为队伍容量。套一下最大流的模板,如果最大流等于总人数,表示有可行的方案,看最终的残余网络,那些边有流残留,表示选择了这条路。。输出就行了。
代码:#include<iostream>#include<cstdio>#include<cstring>#include<string.h>#include<vector>#include<queue>using namespace std;const int maxn = 200;const int inf = 1e9;int n , m , sum;bool ans[maxn][maxn];
struct Edge{ Edge(int uu,int vv,int flow,int cap) : u(uu) , v(vv) , flow(flow) , cap(cap) { } int u , v; int flow , cap;};
vector<Edge> edge;vector<int> G[maxn];
void add(int s,int t,int cap){ edge.push_back(Edge(s,t,0,cap)); edge.push_back(Edge(t,s,0,0)); int x = edge.size(); G[s].push_back(x-2); G[t].push_back(x-1);}
void input(){ sum = 0; for (int i = 0 ; i <= n+m+1 ; ++i) G[i].clear(); edge.clear(); for (int i = 1 ; i <= n ; ++i) { int x; scanf("%d",&x); sum += x; add(i,n+m+1,x); } for (int i = 1 ; i <= m ; ++i) { int x; scanf("%d",&x); add(0,n+i,x); for (int j = 1 ; j <= n ; ++j) add(n+i,j,1); }}
struct ISAP { int num[maxn] , d[maxn] , p[maxn] , cur[maxn]; int s , t , n; void bfs() { queue<int> q; q.push(t); for (int i = 0 ; i < n ; ++i) d[i] = inf; d[t] = 0; while (q.size()) { int u = q.front(); q.pop(); for (int i = 0 ; i < G[u].size() ; ++i) { Edge & e = edge[G[u][i]]; if (e.cap == 0 && d[e.v]==inf) { d[e.v] = d[u]+1; q.push(e.v); } } } }
int Augment() { int x = t , a = inf; while (x!=s) { Edge & e = edge[p[x]]; a = min(a,e.cap-e.flow); x = e.u; } x = t; while (x!=s) { edge[p[x]].flow += a; edge[p[x]^1].flow -= a; x = edge[p[x]].u; } return a; }
int maxflow(int s,int t,int n) { this->s = s , this->t = t , this->n = n; memset(cur,0,sizeof(cur)); memset(num,0,sizeof(num)); bfs(); int x = s , flow = 0; for (int i = 0 ; i < n ; ++i) if (d[i]!=inf) ++num[d[i]]; while (d[s] < n) { if (x==t) { flow += Augment(); x = s; } bool ok = false; for (int i = cur[x] ; i < G[x].size() ; ++i) { Edge & e = edge[G[x][i]]; if (e.cap > e.flow && d[x]==d[e.v]+1) { p[e.v] = G[x][i]; ok = true; cur[x] = i; x = e.v; break; } } if (!ok) { int k = n-1; for (int i = 0 ; i < G[x].size() ; ++i) { Edge & e = edge[G[x][i]]; if (e.cap > e.flow) k = min(k,d[e.v]); } if (--num[d[x]]==0) break; cur[x] = 0; ++num[d[x]=k+1]; if (x!=s) x = edge[p[x]].u; } } return flow; }}solver;
int main(){ while (scanf("%d%d",&n,&m)==2,n+m) { input(); int ret = solver.maxflow(0,n+m+1,n+m+2); if (ret!=sum) { printf("0\n"); continue; } printf("1\n"); memset(ans,0,sizeof(ans)); for (int i = 1 ; i <= n ; ++i) { for (int j = 0 ; j < G[i].size() ; ++j) { Edge & e = edge[G[i][j]]; if (e.flow == -1) ans[i][e.v-n] = true; } } for (int i = 1 ; i <= n ; ++i) { bool first = true; for (int j = 1 ; j <= m ; ++j) if (ans[i][j]) { if (first) first = false; else printf(" "); printf("%d",j); } printf("\n"); } }}
The Grand Dinner
Input: standard input
Output:
standard output
Time Limit: 15 seconds
Memory Limit: 32 MB
Each team participating in this
year’s ACM World Finals contest is
expected to join the grand dinner to be arranged after the prize giving ceremony
ends. In order to maximize the interaction among the members of different teams,
it is expected that no two members of the same team sit at the same table.
Now, given the number of members
in each team (including contestants, coaches, reserves, guests etc.) and the
seating capacity of each available table, you are to determine whether it is
possible for the teams to sit as described in the previous paragraph. If such an
arrangement is possible you must also output one possible seating arrangement.
If there are multiple possible arrangements, any one is acceptable.
Input
The input file may contain multiple test cases. The
first line of each test case contains two integers M (1 ?
M ?
70) and N (1 ?
N ?
50) denoting the number of teams and the number of tables respectively. The
second line of the test case contains M integers where the i-th (1 ?
i ?
M) integer mi (1 ?
mi?
100) indicates the number of members of team i. The third line contains N integers where the j-th (1 ?
j ?
N) integer nj (2 ?
nj?
100) indicates the seating capacity of table j.
A test case containing two zeros
for M and N terminates the input.
Output
For each test case in the input
print a line containing either 1 or
0 depending on whether or not there
exists a valid seating arrangement of the team members. In case of a successful
arrangement print M additional lines where the i-th (1 ?
i ?
M) of these lines contains a table number (an integer from 1 to N) for each of the members of
team i.
Sample Input
4
5
4 5
3 5
3 5
2 6 4
4
5
4 5
3 5
3 5
2 6 3
0
0
Sample Output
1
1 2
4 5
1 2
3 4 5
2 4
5
1 2
3 4 5
0
(World Finals Warm-up Contest,
Problem Setter: Rezaul Alam Chowdhury)
代码:有个M个队伍,N个桌子,你要为这些人安排位子,不能有两个同队的人做在一张桌子上。问怎么安排。
思路:我们可以用网络流来做,有一个源点连向每一个桌子,容量为桌子的容量,桌子连向每一个队伍,容量为1,每个队伍连向一个汇点,容量为队伍容量。套一下最大流的模板,如果最大流等于总人数,表示有可行的方案,看最终的残余网络,那些边有流残留,表示选择了这条路。。输出就行了。
代码:#include<iostream>#include<cstdio>#include<cstring>#include<string.h>#include<vector>#include<queue>using namespace std;const int maxn = 200;const int inf = 1e9;int n , m , sum;bool ans[maxn][maxn];
struct Edge{ Edge(int uu,int vv,int flow,int cap) : u(uu) , v(vv) , flow(flow) , cap(cap) { } int u , v; int flow , cap;};
vector<Edge> edge;vector<int> G[maxn];
void add(int s,int t,int cap){ edge.push_back(Edge(s,t,0,cap)); edge.push_back(Edge(t,s,0,0)); int x = edge.size(); G[s].push_back(x-2); G[t].push_back(x-1);}
void input(){ sum = 0; for (int i = 0 ; i <= n+m+1 ; ++i) G[i].clear(); edge.clear(); for (int i = 1 ; i <= n ; ++i) { int x; scanf("%d",&x); sum += x; add(i,n+m+1,x); } for (int i = 1 ; i <= m ; ++i) { int x; scanf("%d",&x); add(0,n+i,x); for (int j = 1 ; j <= n ; ++j) add(n+i,j,1); }}
struct ISAP { int num[maxn] , d[maxn] , p[maxn] , cur[maxn]; int s , t , n; void bfs() { queue<int> q; q.push(t); for (int i = 0 ; i < n ; ++i) d[i] = inf; d[t] = 0; while (q.size()) { int u = q.front(); q.pop(); for (int i = 0 ; i < G[u].size() ; ++i) { Edge & e = edge[G[u][i]]; if (e.cap == 0 && d[e.v]==inf) { d[e.v] = d[u]+1; q.push(e.v); } } } }
int Augment() { int x = t , a = inf; while (x!=s) { Edge & e = edge[p[x]]; a = min(a,e.cap-e.flow); x = e.u; } x = t; while (x!=s) { edge[p[x]].flow += a; edge[p[x]^1].flow -= a; x = edge[p[x]].u; } return a; }
int maxflow(int s,int t,int n) { this->s = s , this->t = t , this->n = n; memset(cur,0,sizeof(cur)); memset(num,0,sizeof(num)); bfs(); int x = s , flow = 0; for (int i = 0 ; i < n ; ++i) if (d[i]!=inf) ++num[d[i]]; while (d[s] < n) { if (x==t) { flow += Augment(); x = s; } bool ok = false; for (int i = cur[x] ; i < G[x].size() ; ++i) { Edge & e = edge[G[x][i]]; if (e.cap > e.flow && d[x]==d[e.v]+1) { p[e.v] = G[x][i]; ok = true; cur[x] = i; x = e.v; break; } } if (!ok) { int k = n-1; for (int i = 0 ; i < G[x].size() ; ++i) { Edge & e = edge[G[x][i]]; if (e.cap > e.flow) k = min(k,d[e.v]); } if (--num[d[x]]==0) break; cur[x] = 0; ++num[d[x]=k+1]; if (x!=s) x = edge[p[x]].u; } } return flow; }}solver;
int main(){ while (scanf("%d%d",&n,&m)==2,n+m) { input(); int ret = solver.maxflow(0,n+m+1,n+m+2); if (ret!=sum) { printf("0\n"); continue; } printf("1\n"); memset(ans,0,sizeof(ans)); for (int i = 1 ; i <= n ; ++i) { for (int j = 0 ; j < G[i].size() ; ++j) { Edge & e = edge[G[i][j]]; if (e.flow == -1) ans[i][e.v-n] = true; } } for (int i = 1 ; i <= n ; ++i) { bool first = true; for (int j = 1 ; j <= m ; ++j) if (ans[i][j]) { if (first) first = false; else printf(" "); printf("%d",j); } printf("\n"); } }}
相关文章推荐
- UVA 10249 - The Grand Dinner(网络流 or 贪心)
- UVa Problem 10249 The Grand Dinner - 网络流解题
- UVA - 10249 The Grand Dinner
- UVA - 10249 The Grand Dinner
- UVA-10249 - The Grand Dinner(最大流)
- UVA - 10249 The Grand Dinner
- UVa10249 - The Grand Dinner(为什么超时)
- 10249 - The Grand Dinner 最大流
- 10249 The Grand Dinner
- UVa Problem 10249 The Grand Dinner (丰盛的晚餐)
- (beginer) 网络流(拆点)UVA 12125 - March of the Penguins
- (beginer)网络流(最小割最大流) UVA 1212 - Duopoly
- (beginer) 网络流(拆点) UVA 563 Crimewave
- (beginer) 网络流(区间模型+最大费用流) UVA 1317 Concert Hall Scheduling
- (beginer) 网络流(最小费用流+费用跟流量有关) UVA 1486 - Transportation
- Uva 10983 Buy one, get the rest free(网络流/时序模型)
- UVA 11380 - Down Went The Titanic(网络流)
- March of the Penguins - UVa 12125 网络流
- (beginer) 半平面交 UVA 11265 The Sultan's Problem
- (beginer) 网络流(最大流+二分) UVA 1345 - Jamie\'s Contact Groups