题意:给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; }