首页 > 代码库 > UESTC 898 方老师和缘分 --二分图匹配+强连通分量
UESTC 898 方老师和缘分 --二分图匹配+强连通分量
这题原来以为是某种匹配问题,后来好像说是强连通的问题。
做法:建图,每个方老师和它想要的缘分之间连一条有向边,然后,在给出的初始匹配中反向建边,即如果第i个方老师现在找到的是缘分u,则建边u->i。这样求出所有的强连通分量,每个强连通分量中方老师和缘分的数目一定是相等的,所以每个方老师一定可以找到与他在同一个强连通分量里的缘分,因为强连通分量中每个点都是可达的,某个方老师找到了其强连通分量中的非原配点,则该原配缘分一定可以在强连通分量中找到"新欢"。可以画个图看看。
由于要构造非二分图,缘分的编号从n+1开始,到2n。
代码:
#include <iostream>#include <cstdio>#include <cstring>#include <cmath>#include <algorithm>#include <vector>#include <queue>#include <stack>#define Mod 1000000007using namespace std;#define N 200007std::vector<int> G[4005];int low[4005],dfn[4005];int instk[4005],bel[4005];int n,Time,cnt,res;stack<int> stk;int ans[2005];void Tarjan(int u){ low[u] = dfn[u] = ++Time; stk.push(u); instk[u] = 1; for(int i=0;i<G[u].size();i++) { int v = G[u][i]; if(!dfn[v]) { Tarjan(v); low[u] = min(low[u],low[v]); } else if(instk[v]) low[u] = min(low[u],dfn[v]); } if(low[u] == dfn[u]) { cnt++; int v; do { v = stk.top(); stk.pop(); instk[v] = 0; bel[v] = cnt; }while(u != v); }}void init(){ memset(G,0,sizeof(G)); memset(instk,0,sizeof(instk)); memset(bel,-1,sizeof(bel)); memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn)); Time = cnt = 0; while(!stk.empty()) stk.pop();}int main(){ int i,j,u,v,k; while(scanf("%d",&n)!=EOF) { init(); for(i=1;i<=n;i++) { scanf("%d",&k); while(k--) { scanf("%d",&v); G[i].push_back(v+n); } } for(i=1;i<=n;i++) { scanf("%d",&v); G[v+n].push_back(i); } for(i=1;i<=n;i++) { if(!dfn[i]) Tarjan(i); } for(u=1;u<=n;u++) { k = 0; for(i=0;i<G[u].size();i++) { v = G[u][i]; if(bel[u] == bel[v]) ans[k++] = v-n; } sort(ans,ans+k); printf("%d",k); for(i=0;i<k;i++) printf(" %d",ans[i]); printf("\n"); } } return 0;}
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。