uestc 方老师和缘分
关于怎么建图,自己还真是想不出来。
我觉得就是找到每个方老师所在的scc里的所有缘分吧。。
转自http://www.cnblogs.com/whatbeg/p/3765621.html
做法:建图,每个方老师和它想要的缘分之间连一条有向边,然后,在给出的初始匹配中反向建边,即如果第i个方老师现在找到的是缘分u,则建边u->i。这样求出所有的强连通分量,每个强连通分量中方老师和缘分的数目一定是相等的,所以每个方老师一定可以找到与他在同一个强连通分量里的缘分,因为强连通分量中每个点都是可达的,某个方老师找到了其强连通分量中的非原配点,则该原配缘分一定可以在强连通分量中找到"新欢"。可以画个图看看。
由于要构造非二分图,缘分的编号从n+1开始,到2n。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<string> 6 #include<queue> 7 #include<algorithm> 8 #include<map> 9 #include<iomanip> 10 #include<climits> 11 #include<string.h> 12 #include<cmath> 13 #include<stdlib.h> 14 #include<vector> 15 #include<stack> 16 #include<set> 17 using namespace std; 18 #define INF 1000000007 19 #define MAXN 4010 20 #define Mod 1000007 21 #define N 100007 22 #define NN 30 23 #define sigma_size 3 24 const int maxn = 6e5 + 10; 25 using namespace std; 26 typedef long long LL; 27 const double pi = acos(-1); 28 29 30 vector<int> G[MAXN]; 31 int dfn[MAXN], low[MAXN], instk[MAXN], sccno[MAXN], ans[MAXN]; 32 stack<int> S; 33 int Time, cnt ,n, res; 34 void Tarjan(int u) 35 { 36 dfn[u] = low[u] = ++Time; 37 S.push(u); 38 instk[u] = 1; 39 for (int i = 0; i < G[u].size(); ++i) { 40 int v = G[u][i]; 41 if (!dfn[v]) { 42 Tarjan(v); 43 low[u] = min(low[u], low[v]); 44 } 45 else if (instk[v]) { 46 low[u] = min(low[u], dfn[v]); 47 } 48 } 49 if (low[u] == dfn[u]) { 50 cnt++; 51 int v; 52 do{ 53 v = S.top(); 54 S.pop(); 55 instk[v] = 0; 56 sccno[v] = cnt; 57 } while (v != u); 58 } 59 } 60 61 void find_scc() 62 { 63 for (int i = 1; i <= n; ++i) 64 if (!dfn[i]) Tarjan(i); 65 } 66 67 void init() 68 { 69 for (int i = 0; i <= n; ++i) 70 G[i].clear(); 71 Time = cnt = 0; 72 memset(dfn, 0, sizeof(dfn)); 73 memset(low, 0, sizeof(low)); 74 memset(sccno,0,sizeof(sccno)); 75 memset(instk, 0, sizeof(instk)); 76 while (!S.empty()) S.pop(); 77 } 78 79 int main() 80 { 81 int k, u, v; 82 while (~scanf("%d",&n)) { 83 init(); 84 for (int i = 1; i <= n; ++i) { 85 scanf("%d", &k); 86 for (int j = 0; j < k; ++j) { 87 cin >> v; 88 G[i].push_back(v + n); 89 } 90 } 91 for (int i = 1; i <= n; ++i) { 92 scanf("%d", &v); 93 G[v + n].push_back(i); 94 } 95 find_scc(); 96 for (int u = 1; u <= n; ++u) { 97 k = 0; 98 for (int i = 0; i < G[u].size(); ++i) { 99 v = G[u][i]; 100 if (sccno[u] == sccno[v]) 101 ans[k++] = v - n; 102 } 103 sort(ans, ans + k); 104 printf("%d", k); 105 for (int i = 0; i < k; ++i) 106 printf(" %d",ans[i]); 107 puts(""); 108 } 109 } 110 return 0; 111 }