原题位置: http://cogs.sxysxy.org:8080/cogs/problem/problem.php?pid=729
(这个有SPJ)
这个题是一个裸的网络流板子题,都说网络流难在建图,我只能说+1;
这个题的建图方式有两种,但大同小异;
<1> 超级源,超级汇,拆点,拆出的两个点之间为代表数(桌子数),代表和桌子之间的边是1,超级源(汇)与代表(桌子)之间是正无穷;
<2> 超级源,超级汇,超级源(汇)与代表(桌子)之间是代表数(桌子数),代表与桌子之间是1;
(我用的是<1>)
然后跑最大流了,如果最大流等于代表数的话,即所有代表都可以合法的找到桌子,即输出1,否则输出0;
这题描述不清,输出0的话就可以exit(0)了;
至于这道题的一个点就是输出路径(??!路径??!);
就看如果代表和桌子之间的正向边没流量的话,证明该代表选了这张桌子,然后输出就好了;
要是WA了,就开大点数组,然后找个有SPJ的网站,如果还没A,就自行debug吧;
—————————————123——————————————-
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
#define II int
#define B bool
#define R register
#define I 1000
using namespace std;
struct node {
II from,to;
II flow;
};
vector <node> Q;
vector <II> aa[I*I];
II dis[I], bit[I], kl[I][I], peo[I], tab[I];
II n,m,ans,en,_tot;
void add(R II x,R II y,R II z)
{
Q.push_back((node) {x,y,z});
aa[x].push_back(Q.size()-1);
Q.push_back((node) {y,x,0});
aa[y].push_back(Q.size()-1);
}
B bfs()
{
queue <II> op;
op.push(0);
dis[0]=1;
while (!op.empty()) {
II o=op.front(); op.pop();
for(R II i=0;i<aa[o].size();i++)
{
R node now=Q[aa[o][i]];
R II go=now.to;
if(!dis[go]&&now.flow) {
dis[go]=dis[o]+1;
op.push(go);
}
}
}
return dis[en];
}
II dfs(R II x,R II a)
{
R II f=0,now_flow=0;
if(!a||x==en) return a;
for(R II& i=bit[x];i<aa[x].size();i++)
{
R node& now=Q[aa[x][i]];
R II go=now.to;
if(dis[go]==dis[x]+1&&(f=dfs(go,min(a,now.flow)))>0) {
now_flow+=f;
Q[aa[x][i]].flow-=f;
a-=f;
Q[aa[x][i]^1].flow+=f;
if(!a) return now_flow;
}
}
return now_flow;
}
int main()
{
freopen("roundtable.in","r",stdin);
freopen("roundtable.out","w",stdout);
// freopen("1.in","r",stdin);
scanf("%d%d",&n,&m);
for(R II i=1;i<=n;i++) scanf("%d",&peo[i]), _tot+=peo[i];
for(R II i=1;i<=m;i++) scanf("%d",&tab[i]);
en=n+n+m+m+1;
for(R II i=1;i<=n;i++) add(0,i,123456789);
for(R II i=n+n+m+1;i<=n+n+m+m;i++) add(i,en,123456789);
for(R II i=1;i<=n;i++) add(i,n+i,peo[i]);
for(R II i=n+n+1;i<=n+n+m;i++) add(i,m+i,tab[i-n-n]);
for(R II i=n+1;i<=n+n;i++)
{
for(R II j=n+n+1;j<=n+n+m;j++)
add(i,j,1);
}
while (bfs()) {
for(R II i=0;i<=en;i++) bit[i]=0;
ans+=dfs(0,123456789);
for(R II i=0;i<=en;i++) dis[i]=0;
}
ans==_tot? printf("1\n"): printf("0\n");
if(ans==_tot) {
for(R II i=n+1;i<=n+n;i++)
{
for(R II j=0;j<aa[i].size();j++)
{
if(!Q[aa[i][j]].flow) printf("%d ",Q[aa[i][j]].to-n-n);
// 找路径,如果该正向边没流量的话,输出;
}
printf("\n");
}
}
exit(0);
}
————————————–456———————————————
by pretend-fal
END;