最大流+二分,建图跟3081差不多,这里就省略, code 如下。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define MAXVERTEX 800
#define INF 0x7fffffff
#define MAXARC MAXVERTEX*MAXVERTEX
using namespace std;
struct Edge {
int v, val, next;
}edge[MAXARC];
struct Point {
int x, y;
}point[MAXARC];
int s_v, e_v, e_cnt, vertex;
int graph[MAXVERTEX][MAXVERTEX];
int used[MAXVERTEX][MAXVERTEX], root[MAXVERTEX];
int pre[MAXVERTEX], dis[MAXVERTEX], cur[MAXVERTEX], head[MAXVERTEX], gap[MAXVERTEX];
int get_root(int x)
{
if( x == root[x] ) return x;
return root[x] = get_root(root[x]);
}
void insert_arc(int u, int v, int w)
{
edge[e_cnt].v = v; edge[e_cnt].val = w;
edge[e_cnt].next = head[u]; head[u] = e_cnt ++;
swap(u, v);
edge[e_cnt].v = v; edge[e_cnt].val = 0;
edge[e_cnt].next = head[u]; head[u] = e_cnt ++;
}
void establish_graph(int m, int arc, int k)
{
int x, y;
e_cnt = 0;
memset(used, 0, sizeof(used));
memset(head, -1, sizeof(head));
for(int i = 1; i <= vertex; i ++) {
insert_arc(s_v, i, m); insert_arc(i, i+vertex, k);
}
for(int i = 2*vertex+1; i <= 3*vertex; i ++) {
insert_arc(i, e_v, m);
}
for(int i = 0; i < arc; i ++) {
x = point[i].x; y = point[i].y;
for(int j = 1; j <= vertex; j ++) {
if( root[x] == root[j] && !used[j][y] ) {
insert_arc(j, y+2*vertex, 1); used[j][y] = 1;
}
}
}
for(int i = 1; i <= vertex; i ++) {
for(int j = 1; j <= vertex; j ++) {
if( !used[i][j] ) {
insert_arc(i+vertex, j+2*vertex, 1);
}
}
}
}
void bfs(int src, int des)
{
int u, v;
queue<int> q;
memset(dis, -1, sizeof(dis));
memset(gap, 0, sizeof(gap));
dis[des] = 0; gap[0] = 1;
q.push(des);
while( !q.empty() ) {
u = q.front(); q.pop();
for(int i = head[u]; -1 != i; i = edge[i].next) {
v = edge[i].v;
if( edge[i].val || -1 != dis[v] ) continue;
dis[v] = dis[u]+1; gap[dis[v]] ++;
q.push(v);
}
}
}
int i_sap(int source, int sink)
{
int u(source), v, min_dis, max_flow(0), path_flow(INF);
bfs(source, sink);
for(int i = 0; i <= e_v; i ++)
cur[i] = head[i];
pre[u] = u;
while( dis[source] < e_v ) {
loop:
for(int &i = cur[u]; -1 != i; i = edge[i].next) {
v = edge[i].v;
if( !edge[i].val || (dis[u] != dis[v]+1) ) continue;
pre[v] = u; path_flow = min(path_flow, edge[i].val);
u = v;
if( v == sink ) {
for(u = pre[u]; v != source; v = u, u = pre[u]) {
edge[cur[u]].val -= path_flow; edge[cur[u]^1].val += path_flow;
}
max_flow += path_flow; path_flow = INF;
}
goto loop;
}
min_dis = e_v;
for(int i = head[u]; -1 != i; i = edge[i].next) {
v = edge[i].v;
if( edge[i].val && min_dis > dis[v] ) {
min_dis = dis[v]; cur[u] = i;
}
}
gap[dis[u]] --;
if( !gap[dis[u]] ) break;
dis[u] = min_dis+1;
gap[ dis[u] ] ++; u = pre[u];
}
//printf("max_flow = %d\n", max_flow);
return max_flow;
}
template<class T> inline void read(T& x)
{
char c;
int mul = 1;
while((c = getchar()) != EOF)
{
if(c == '-')mul = -1;
if(c >= '0' && c <= '9')
{
x = c-'0';
break;
}
}
if(c == EOF){x = EOF;return;}
while(c = getchar())
{
if(c >= '0' && c <= '9')
{
x = (x<<1)+(x<<3)+(c-'0');
}
else break;
}
x *= mul;
}
int main(int argc, char const *argv[])
{
//freopen("test.in", "r", stdin);
int ans, cnt, arc, k, match, l, r, m, x, y, r_x, r_y;
//scanf("%d", &cnt);
read(cnt);
while( cnt-- ) {
//scanf("%d %d %d %d", &vertex, &arc, &k, &match);
read(vertex); read(arc); read(k); read(match);
for(int i = 0; i < arc; i ++) {
//scanf("%d %d", &point[i].x, &point[i].y);
read(point[i].x); read(point[i].y);
}
for(int i = 0; i <= vertex; i ++)
root[i] = i;
for(int i = 0; i < match; i ++) {
//scanf("%d %d", &x, &y);
read(x); read(y);
x = get_root(x); y = get_root(y);
if( r_x != r_y ) root[x] = y;
}
for(int i = 0; i <= vertex; i ++)
root[i] = get_root(i);
s_v = vertex*3+1, e_v = s_v+1;
l = 0; r = vertex; ans = 0;
while( l <= r ) {
m = (l+r)>>1; establish_graph(m, arc, k);
if( vertex*m == i_sap(s_v, e_v) ) {
ans = m; l = m+1;
}
else
r = m-1;
}
printf("%d\n", ans);
}
return 0;
}
hdu_3277
最新推荐文章于 2017-07-31 23:31:00 发布