# 【题解】Inspection UVa 1440 LA 4597 NEERC 2009

  1 #include <algorithm>
2 #include <cstring>
3 #include <cstdio>
4 #include <queue>
5
6 using namespace std;
7 const int INF = 0x3f3f3f3f;
8 const int MAXN = 110;
9
10 namespace ISAP {
11     const int MAXV = MAXN;
12     const int MAXE = ( MAXV*MAXV/2 + MAXV*2 )*3;
13
14     struct Edge {
15         int u, v, c, f;
16         Edge(){}
17         Edge( int u, int v, int c, int f ):
18             u(u),v(v),c(c),f(f){}
19     }edge[MAXE<<1];
20     int n, m, s, t, ss, tt;
21     int head[MAXV], nxt[MAXE<<1], eid[MAXE<<1], eidx;
22     void init( int n2, int ss2, int tt2 ) { // 初始化，设置附加源和附加汇
23         n = n2; ss = ss2; tt = tt2;
24         m = eidx = 0;
26     }
27     int adde( int u, int v, int c ) { // 添加一条只有上界的边
28         int rtn = m;
30         edge[m++] = Edge(u,v,c,0);
32         edge[m++] = Edge(v,u,0,0);
33         return rtn;
34     }
35     int adde2( int u, int v, int b, int c ) { // 添加一条有上下界的边，返回边的下标
39         return rtn;
40     }
41     // 以下ISAP板子
42     int prev[MAXV], dist[MAXV], num[MAXV], cur[MAXV], res[MAXV];
43     queue<int> bfsq;
44     void bfs() {
45         for( int i = 1; i <= n; ++i ) dist[i] = n;
46         dist[t] = 0; bfsq.push(t);
47         while( !bfsq.empty() ) {
48             int u = bfsq.front(); bfsq.pop();
49             for( int i = head[u]; ~i; i = nxt[i] ) {
50                 Edge &e = edge[eid[i]];
51                 if( dist[e.v] == n ) {
52                     dist[e.v] = dist[u] + 1;
53                     bfsq.push(e.v);
54                 }
55             }
56         }
57     }
58     void augment() {
59         int u = t, flow = res[t];
60         while( u != s ) {
61             int i = prev[u];
62             edge[i].f += flow;
63             edge[i^1].f -= flow;
64             u = edge[i].u;
65         }
66     }
67     bool advance( int &u ) {
68         for( int i = cur[u]; ~i; i = nxt[i] ) {
69             Edge &e = edge[eid[i]];
70             if( e.c > e.f && dist[e.v] + 1 == dist[u] ) {
71                 prev[e.v] = cur[u] = i;
72                 res[e.v] = min( res[u], e.c - e.f );
73                 u = e.v;
74                 return true;
75             }
76         }
77         return false;
78     }
79     bool retreat( int &u ) {
80         if( --num[dist[u]] == 0 ) return false;
81         int newd = n;
82         for( int i = head[u]; ~i; i = nxt[i] ) {
83             Edge &e = edge[eid[i]];
84             if( e.c > e.f ) newd = min( newd, dist[e.v] + 1 );
85         }
86         ++num[ dist[u] = newd ];
88         if( u != s ) u = edge[prev[u]].u;
89         return true;
90     }
91     int solve( int s2, int t2 ) { // 以s2为源，t2为汇跑最大流
92         s = s2; t = t2;
93         bfs();
94         for( int i = 1; i <= n; ++i )
96         int u = s, flow = 0;
97         res[s] = INF;
98         while( dist[s] < n ) {
99             if( u == t ) {
100                 augment();
101                 flow += res[t];
102                 u = s;
103             }
105                 if( !retreat(u) )
106                     break;
107         }
108         return flow;
109     }
110 }
111
112 int n, s, t, ss, tt; // 点的个数，源，汇，附加源，附加汇
113
114 namespace Solve {
116     using ISAP::nxt;
117     using ISAP::eid;
118     using ISAP::Edge;
119     using ISAP::edge;
120     bool first;
121     void dfs( int u ) { // dfs输出方案
122         // printf( "Debug: u = %d\n", u );
123         if( !first ) putchar(' ');
124         first = false;
125         printf( "%d", u );
126         for( int i = head[u]; ~i; i = nxt[i] ) {
127             Edge &e = edge[eid[i]];
128             if( e.v <= n && e.f > 0 ) { // 任选一条边走下去
129                 // printf( "going eid = %d, from %d to %d, flow_left = %d\n", eid[i], e.u, e.v, e.f );
130                 --e.f;
131                 dfs(e.v);
132                 return;
133             }
134         }
135     }
136     void addbound() { // 把每条边流量加上下界，恢复成原图的样子，方便输出方案
137         using ISAP::m;
138         for( int i = 0; i < m; ++i ) {
139             Edge &e = edge[eid[i]];
140             if( e.u <= n && e.v <= n && e.c > 0 )
141                 ++e.f;
142         }
143     }
144 }
145
146 namespace Debug { // 调试用QwQ
147     void print_flow() {
148         using ISAP::edge;
149         using ISAP::Edge;
150         using ISAP::eid;
151         using ISAP::m;
152         for( int i = 0; i < m; ++i ) {
153             Edge &e = edge[eid[i]];
154             if( e.u <= n && e.v <= n && e.c > 0 )
155                 printf( "eid = %d, from %d to %d, flow = %d\n", eid[i], e.u, e.v, e.f );
156         }
157     }
158     void print_flow2() {
159         using ISAP::edge;
160         using ISAP::Edge;
161         using ISAP::eid;
162         using ISAP::m;
163         for( int i = 0; i < m; ++i ) {
164             Edge &e = edge[eid[i]];
165             if( e.f > 0 )
166                 printf( "eid = %d, from %d to %d, flow = %d\n", eid[i], e.u, e.v, e.f );
167         }
168     }
169 }
170
171 int main() {
172     while( scanf( "%d", &n ) == 1 ) {
173         s = n+1, t = n+2, ss = n+3, tt = n+4;
174         ISAP::init(tt,ss,tt);
175         for( int i = 1; i <= n; ++i ) {
176             int mi; scanf( "%d", &mi );
177             while( mi-- ) {
178                 int v; scanf( "%d", &v );
180             }
183         }
184         int flow1 = ISAP::solve(ss,tt);
185         // printf( "flow1 = %d\n", flow1 );
186         // Debug::print_flow();
187         // Debug::print_flow2();
188         int tsedge = ISAP::adde2(t,s,0,INF); // 存储弧<t,s>的信息，调试用QwQ
189         int ans = ISAP::solve(ss,tt);
190         // printf( "t_s flow = %d\n", ISAP::edge[tsedge].f );
191         // Debug::print_flow();
192         // Debug::print_flow2();
193         printf( "%d\n", ans );
195         while( ans ) {
196             using namespace Solve;
197             for( int i = head[s]; ~i; i = nxt[i] ) {
198                 Edge &e = edge[eid[i]];
199                 if( e.v <= n && e.f > 0 ) { // 任选一个点dfs，输出方案
200                     first = true;
201                     --e.f;
202                     --ans;
203                     dfs(e.v);
204                         putchar('\n');
205                 }
206             }
207         }
208     }
209     return 0;
210 }

posted @ 2017-04-19 18:49  mlystdcall  阅读(...)  评论(... 编辑 收藏