您的位置:首页 > 理论基础 > 计算机网络

HDU 4265 Science! 网络流解多重匹配,输出所有比配可能

2016-01-11 20:16 459 查看
题意:给n个人,n个地方,每一轮每个人必须站到一个地方上,每个地方只能站一个人,这是一轮游戏,进行多轮,但是每一轮同一个人不能站在相同的地方上。



想法:这一题的第一步求出最大的游戏轮数和女生找男朋友那一题差不多,用二分+网络流即可得出解,剩下的部分就是找出这k种解,开始,我在原图的残余网络上直接找,每次找一组就标记一下输出,但是这样不对(不知为何),然后另一种方法就是比较笨的方法了,就是先把没有关系的边删除,然后找k次,每次跑一边网络流,s到个点的容量为1,这样就可以保证残留网络中有一组解,然后,输出这些解,然后删掉这一组解所对应的边,这样就OK了。

建边:

1.虚拟超级source和sink

2.source到每一个人连一条容量为k的边

3.每一个地方到sink连一条容量为k的边(2,3中的k在不同地方要进行不同的调整)

4.人与地方之间的关系连一条容量为1的边



#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#define inf 0x7fffffff
using namespace std;
const int nodes=200;
const int edges=40000+50;
int n,s,t;
struct node
{
int v,next,flow;
}e[edges];
int head[nodes],cur[nodes],cnt;
char map[nodes][nodes];
class Dinic
{
public:
int spath()
{
queue<int>q;
while(!q.empty()) q.pop();
memset(dis,-1,sizeof(dis));
dis[s]=0;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=head[u];i+1;i=e[i].next)
{
int v=e[i].v;
if(dis[v]==-1&&e[i].flow>0)
{
dis[v]=dis[u]+1;
q.push(v);
}
}
}
return dis[t]!=-1;
}
int Min(int a,int b)
{
if(a<b) return a;
return b;
}
int dfs(int u,int flow)
{
int cost=0;
if(u==t) return flow;
for(int &i=cur[u];i+1;i=e[i].next)
{
//cur[u]=i;
int v=e[i].v;
if(dis[v]==dis[u]+1&&e[i].flow>0)
{
int minn=dfs(v,Min(e[i].flow,flow-cost));
if(minn>0)
{
e[i].flow-=minn;
e[i^1].flow+=minn;
cost+=minn;
if(cost==flow) break;
}
else dis[v]=-1;
}
}
return cost;
}
int result()
{
int xx=0;
while(spath())
{
for(int i=s;i<=t;i++) cur[i]=head[i];
xx+=dfs(s,inf);
}
return xx;
}
private:
int dis[nodes];
}dinic;
void Init()
{
memset(head,-1,sizeof(head));
cnt=0;
}
void add(int a,int b,int c)
{
e[cnt].v=b;
e[cnt].next=head[a];
e[cnt].flow=c;
head[a]=cnt++;

e[cnt].v=a;
e[cnt].flow=0;
e[cnt].next=head[b];
head[b]=cnt++;
}
void build_map(int val)
{
Init();
for(int i=1;i<=n;i++)
{
add(s,i,val);
add(i+n,t,val);
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(map[i][j]=='Y')
{
add(i,j+n,1);
}
}
}
}
int find_mid()
{
int low=0,up=n,ans=0;
while(low<=up)
{
int mid=(low+up)>>1;
build_map(mid);
if(dinic.result()==mid*n)
{
ans=mid;
low=mid+1;
}
else up=mid-1;
}
return ans;
}
void find_one_ans_del()
{
int res[nodes];
for(int i=1;i<=n;i++)
{
for(int j=head[i];j+1;j=e[j].next)
{
int v=e[j].v;
if(v!=s&&!e[j].flow)
{
res[v-n]=i;
map[i][v-n]='N';
break;
}
}
}
for(int i=1;i<=n;i++)
{
if(i==1) printf("%d",res[i]);
else printf(" %d",res[i]);
}
printf("\n");
/*for(int i=1;i<=n;i++)
{
for(int j=head[i];j+1;j=e[j].next)
{
int v=e[j].v;
if(v!=s&&e[j].flow==0)
{
map[i][v-n]='N';
break;
}
}
}*/
}
void treatment(int rmid)
{
printf("%d\n",rmid);
build_map(rmid);
dinic.result();
for(int i=1;i<=n;i++)
{
for(int j=head[i];j+1;j=e[j].next)
{
int v=e[j].v;
if(v!=s&&e[j].flow==1)
{
map[i][v-n]='N';
}
}
}
while(rmid--)
{
build_map(1);
dinic.result();
find_one_ans_del();
}
}
int main()
{
while(~scanf("%d",&n),n)
{
for(int i=1;i<=n;i++)
{
scanf("%s",map[i]+1);
}
s=0;t=2*n+1;
int kr=find_mid();
treatment(kr);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: