总结-网络流24题

马上就国庆了,翻了就是初赛。偶有怠惰,是复习联赛略枯燥的故。于是挖新坑,刷刷有趣的算法自慰。(肯定不会咕咕咕的啦,吧)

飞行员配对方案问题

输出方案数

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); (a) <= (c); ++(a))
#define nR(a,b,c) for(register int a = (b); (a) >= (c); --(a))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ll long long
#define u32 unsigned int
#define u64 unsigned long long
 
#define ON_DEBUGG
 
#ifdef ON_DEBUGG
 
#define D_e_Line printf("\n----------\n")
#define D_e(x) cout << (#x) << " : " << x << endl
#define Pause() system("pause")
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#include <ctime>
#define TIME() fprintf(stderr, "\ntime: %.3fms\n", clock() * 1000.0 / CLOCKS_PER_SEC)

#else
 
#define D_e_Line ;
#define D_e(x) ;
#define Pause() ;
#define FileOpen() ;
#define FileSave() ;
#define TIME() ;
//char buf[1 << 21], *p1 = buf, *p2 = buf;
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
 
#endif
 
using namespace std;
struct ios{
    template<typename ATP>inline ios& operator >> (ATP &x){
        x = 0; int f = 1; char ch;
        for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
        while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ '0'), ch = getchar();
        x *= f;
        return *this;
    }
}io;
 
template<typename ATP>inline ATP Max(ATP a, ATP b){
    return a > b ? a : b;
}
template<typename ATP>inline ATP Min(ATP a, ATP b){
    return a < b ? a : b;
}
template<typename ATP>inline ATP Abs(ATP a){
    return a < 0 ? -a : a;
}

const int N = 1007;
const int M = 2007;

struct Edge{
	int nxt, pre;
}e[M];
int head[N], cntEdge = 1;
inline void add(int u, int v){
	e[++cntEdge] = (Edge){ head[u], v}, head[u] = cntEdge;
}

int n1, n2;
int vis[N], tim, match[N];
inline bool Hungry(int u){
	for(register int i = head[u]; i; i = e[i].nxt){
		int v = e[i].pre;
		if(vis[v] == tim) continue;
		vis[v] = tim;
		if(!match[v] || Hungry(match[v])){
			match[v] = u;
			return true;
		}
	}
	return false;
}

struct Answer{
	int x, y;
	bool operator < (const Answer &com) const{
		return x < com.x;
	}
}ans[N << 1];
int main(){
	io >> n1 >> n2;
	int u, v;
	while(~scanf("%d%d", &u, &v) && u != -1){
		add(u, v + n1);
	}
	
	int sum = 0;
	R(i,1,n1){
		++tim;
		sum += Hungry(i);
	}
	
	if(sum == 0){
		printf("No Solution!");
		return 0;
	}
	printf("%d\n", sum);
	
	int tot = 0;
	R(i,1,n2){
		if(match[i + n1]){
//			printf("%d %d\n", match[i + n1], i);
			ans[++tot] = (Answer){ match[i + n1], i};
		}
	}
	sort(ans + 1, ans + tot + 1);
	R(i,1,tot){
		printf("%d %d\n", ans[i].x, ans[i].y);
	}
	return 0;
}

负载平衡问题

最小费用最大流

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); (a) <= (c); ++(a))
#define nR(a,b,c) for(register int a = (b); (a) >= (c); --(a))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ll long long
#define u32 unsigned int
#define u64 unsigned long long
 
#define ON_DEBUGG
 
#ifdef ON_DEBUGG
 
#define D_e_Line printf("\n----------\n")
#define D_e(x) cout << (#x) << " : " << x << endl
#define Pause() system("pause")
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#include <ctime>
#define TIME() fprintf(stderr, "\ntime: %.3fms\n", clock() * 1000.0 / CLOCKS_PER_SEC)

#else
 
#define D_e_Line ;
#define D_e(x) ;
#define Pause() ;
#define FileOpen() ;
#define FileSave() ;
#define TIME() ;
//char buf[1 << 21], *p1 = buf, *p2 = buf;
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
 
#endif
 
using namespace std;
struct ios{
    template<typename ATP>inline ios& operator >> (ATP &x){
        x = 0; int f = 1; char ch;
        for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
        while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ '0'), ch = getchar();
        x *= f;
        return *this;
    }
}io;
 
template<typename ATP>inline ATP Max(ATP a, ATP b){
    return a > b ? a : b;
}
template<typename ATP>inline ATP Min(ATP a, ATP b){
    return a < b ? a : b;
}
template<typename ATP>inline ATP Abs(ATP a){
    return a < 0 ? -a : a;
}

const int N = 1007;
const int M = 1007;

int S, T;
struct Edge{
	int nxt, pre, from, f, w;
}e[M];
int head[N], cntEdge = 1;
inline void add(int u, int v, int f, int w){
	e[++cntEdge] = (Edge){ head[u], v, u, f, w}, head[u] = cntEdge;
}
inline void Add(int u, int v, int f, int w){
	add(u, v, f, w);
	add(v, u, 0, -w);
}
int dis[N], from[N], vis[N];
int q[N];
inline bool SPFA(){
	R(i,0,T) dis[i] = 0x3f3f3f3f;
    int h = 0, t = 1;
    dis[S] = q[S] = 0;
    vis[S] = 1;
    while(h != t){
    	int u = q[h++]; 
		vis[u] = 0;
    	for(register int i = head[u]; i; i = e[i].nxt){
    		int v = e[i].pre;
    		if(e[i].f && dis[v] > dis[u] + e[i].w){
    			from[v] = i;
    			dis[v] = dis[u] + e[i].w;
    			if(!vis[v]){
    				vis[v] = 1;
    				q[t++] = v;
				}
    			
			}
		}

    }
    return dis[T] != 0x3f3f3f3f;
}
int ans;
inline void MCMF(){
	int i = from[T], flow = 0x3f3f3f3f;
	while(i){
		flow = Min(flow, e[i].f);
		i = from[e[i].from];
	}
	i = from[T];
	while(i){
		e[i].f -= flow, e[i ^ 1].f += flow;
		ans += flow * e[i].w;
		i = from[e[i].from];
	}
}
int a[N];
int main(){
	int n;
	io >> n;
	int sum = 0;
	S = 0, T = n << 1 | 1;
	R(i,1,n){
		io >> a[i];
		sum += a[i];
	}
	sum /= n;
	R(i,1,n) a[i] -= sum;
	R(i,1,n){
		if(a[i] > 0)
			Add(S, i, a[i], 0);
		else
			Add(i + n, T, -a[i], 0);
	}
	R(i,1,n){
		if(i != 1){
			Add(i, i - 1, 0x3f3f3f3f, 1);
			Add(i, i - 1 + n, 0x3f3f3f3f, 1);
		}
		if(i != n){
			Add(i, i + 1, 0x3f3f3f3f, 1);
			Add(i, i + 1 + n, 0x3f3f3f3f, 1);
		}
	}
	Add(n, 1, 0x3f3f3f3f, 1);
	Add(n, 1 + n, 0x3f3f3f3f, 1);
	Add(1, n, 0x3f3f3f3f, 1);
	Add(1, n + n, 0x3f3f3f3f, 1);
	
	while(SPFA()){
		MCMF();
	}
	
	printf("%d", ans);
	return 0;
}

运输问题

最小费用最大流,最大费用则取负处理

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); (a) <= (c); ++(a))
#define nR(a,b,c) for(register int a = (b); (a) >= (c); --(a))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ll long long
#define u32 unsigned int
#define u64 unsigned long long
 
#define ON_DEBUGG
 
#ifdef ON_DEBUGG
 
#define D_e_Line printf("\n----------\n")
#define D_e(x) cout << (#x) << " : " << x << endl
#define Pause() system("pause")
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#include <ctime>
#define TIME() fprintf(stderr, "\ntime: %.3fms\n", clock() * 1000.0 / CLOCKS_PER_SEC)

#else
 
#define D_e_Line ;
#define D_e(x) ;
#define Pause() ;
#define FileOpen() ;
#define FileSave() ;
#define TIME() ;
//char buf[1 << 21], *p1 = buf, *p2 = buf;
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
 
#endif
 
using namespace std;
struct ios{
    template<typename ATP>inline ios& operator >> (ATP &x){
        x = 0; int f = 1; char ch;
        for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
        while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ '0'), ch = getchar();
        x *= f;
        return *this;
    }
}io;
 
template<typename ATP>inline ATP Max(ATP a, ATP b){
    return a > b ? a : b;
}
template<typename ATP>inline ATP Min(ATP a, ATP b){
    return a < b ? a : b;
}
template<typename ATP>inline ATP Abs(ATP a){
    return a < 0 ? -a : a;
}

const int N = 2007;
const int M = 50007;

struct Edge{
	int nxt, pre, from, f, w;
}e[M];
int head[N], cntEdge = 1;
inline void add(int u, int v, int f, int w){
	e[++cntEdge] = (Edge){head[u], v, u, f, w}, head[u] = cntEdge;
}
inline void Add(int u, int v, int f, int w){
	add(u, v, f, w);
	add(v, u, 0, -w);
}

int n, m, S, T;

int dis[N], vis[N], q[N], from[N]; 
inline bool SPFA(){
	R(i,S,T) dis[i] = 0x3f3f3f3f;
	int top = 1;
	dis[S] = 0, q[top] = S, vis[S] = 1;
	while(top){
		int u = q[top--];
		vis[u] = 0;
		for(register int i = head[u]; i; i = e[i].nxt){
			int v = e[i].pre;
			if(e[i].f && dis[v] > dis[u] + e[i].w){
				from[v] = i;
				dis[v] = dis[u] + e[i].w;
				if(!vis[v]){
					vis[v] = 1;
					q[++top] = v;
				}
			}
		}
	}
	return dis[T] != 0x3f3f3f3f;
}
int ans;
inline void MCMF(){
	int i = from[T], flow = 0x3f3f3f3f;
	while(i){
		flow = Min(flow, e[i].f);
		i = from[e[i].from];
	}
	i = from[T];
	while(i){
		e[i].f -= flow, e[i ^ 1].f += flow;
		ans += flow * e[i].w;
		i = from[e[i].from];
	}
}
int cost[N][N];
int tmp1[N], tmp2[N];
int main(){
//FileOpen();
	io >> n >> m;
	T = n + m + 1;
	R(i,1,n){
		int x;
		io >> x;
		tmp1[i] = x;
		Add(S, i, x, 0);
	}
	R(i,1,m){
		int x;
		io >> x;
		tmp2[i] = x;
		Add(i + n, T, x, 0);
	}
	R(i,1,n){
		R(j,1,m){
			int x;
			io >> x;
			Add(i, j + n, 0x3f3f3f3f, x);
			cost[i][j] = x;
		}
	}
	
	while(SPFA()) MCMF();
	printf("%d\n", ans);
	ans = 0;
	cntEdge = 1;
	Fill(head, 0);
	R(i,1,n){
		int x = tmp1[i];
		Add(S, i, x, 0);
	}
	R(i,1,m){
		int x = tmp2[i];
		Add(i + n, T, x, 0);
	}
	R(i,1,n){
		R(j,1,m){
			Add(i, j + n, 0x3f3f3f3f, -cost[i][j]);
		}
	}
	while(SPFA()) MCMF();
	printf("%d", -ans);
	
	return 0; 
}

分配问题

二分图最佳匹配

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); (a) <= (c); ++(a))
#define nR(a,b,c) for(register int a = (b); (a) >= (c); --(a))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ll long long
#define u32 unsigned int
#define u64 unsigned long long
 
#define ON_DEBUGG
 
#ifdef ON_DEBUGG
 
#define D_e_Line printf("\n----------\n")
#define D_e(x) cout << (#x) << " : " << x << endl
#define Pause() system("pause")
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#include <ctime>
#define TIME() fprintf(stderr, "\ntime: %.3fms\n", clock() * 1000.0 / CLOCKS_PER_SEC)

#else
 
#define D_e_Line ;
#define D_e(x) ;
#define Pause() ;
#define FileOpen() ;
#define FileSave() ;
#define TIME() ;
//char buf[1 << 21], *p1 = buf, *p2 = buf;
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
 
#endif
 
using namespace std;
struct ios{
    template<typename ATP>inline ios& operator >> (ATP &x){
        x = 0; int f = 1; char ch;
        for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
        while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ '0'), ch = getchar();
        x *= f;
        return *this;
    }
}io;
 
template<typename ATP>inline ATP Max(ATP a, ATP b){
    return a > b ? a : b;
}
template<typename ATP>inline ATP Min(ATP a, ATP b){
    return a < b ? a : b;
}
template<typename ATP>inline ATP Abs(ATP a){
    return a < 0 ? -a : a;
}

const int N = 50007;
const int M = 50007;

int n, S, T;
struct Edge{
	int nxt, pre, from, w, f;
}e[M];
int head[N], cntEdge = 1;
inline void add(int u, int v, int f, int w){
	e[++cntEdge] = (Edge){ head[u], v, u, w, f}, head[u] = cntEdge;
}
inline void Add(int u, int v, int f, int w){
	add(u, v, f, w);
	add(v, u, 0, -w);
}
int dis[N], q[N], vis[N], from[N];
inline bool SPFA(){
	R(i,S,T) dis[i] = 0x3f3f3f3f;
	int h = 0, t = 1;
	dis[S] = 0, q[h] = S, vis[S] = 1;
	while(h != t){
		int u = q[h++];
		vis[u] = 0;
		for(register int i = head[u]; i; i = e[i].nxt){
			int v = e[i].pre;
			if(e[i].f && dis[v] > dis[u] + e[i].w){
				from[v] = i;
				dis[v] = dis[u] + e[i].w;
				if(!vis[v]){
					vis[v] = 1;
					q[t++] = v;
				}
			}
		}
	}
	return dis[T] != 0x3f3f3f3f;
}
int ans;
inline void MCMF(){
	int i = from[T], flow = 0x3f3f3f3f;
	while(i){
		flow = Min(flow, e[i].f);
		i = from[e[i].from];
	}
	i = from[T];
	while(i){
		ans += e[i].w * flow;
		e[i].f -= flow, e[i ^ 1].f += flow;
		i = from[e[i].from];
	}
}
int cost[107][107];
int main(){
//FileOpen();
	io >> n;
	T = n << 1 | 1;
	R(i,1,n){
		Add(S, i, 1, 0);
	}
	
	R(i,1,n){
		Add(i + n, T, 1, 0);
	}
	R(i,1,n){
		R(j,1,n){
			int x;
			io >> x;
			cost[i][j] = x;
			Add(i, j + n, 1, x);
		}
	}
	while(SPFA()) MCMF();
	printf("%d\n", ans);
	ans = 0;
	cntEdge = 1;
	Fill(head, 0);
	R(i,1,n){
		Add(S, i, 1, 0);
	}
	R(i,1,n){
		Add(i + n, T, 1, 0);
	}
	R(i,1,n){
		R(j,1,n){
			Add(i, j + n, 1, -cost[i][j]);
		}
	}
	while(SPFA()) MCMF();
	printf("%d", -ans);
	return 0;
}

最小路径覆盖问题

DAG最小路径覆盖

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); (a) <= (c); ++(a))
#define nR(a,b,c) for(register int a = (b); (a) >= (c); --(a))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ll long long
#define u32 unsigned int
#define u64 unsigned long long
 
#define ON_DEBUGG
 
#ifdef ON_DEBUGG
 
#define D_e_Line printf("\n----------\n")
#define D_e(x) cout << (#x) << " : " << x << endl
#define Pause() system("pause")
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#include <ctime>
#define TIME() fprintf(stderr, "\ntime: %.3fms\n", clock() * 1000.0 / CLOCKS_PER_SEC)

#else
 
#define D_e_Line ;
#define D_e(x) ;
#define Pause() ;
#define FileOpen() ;
#define FileSave() ;
#define TIME() ;
//char buf[1 << 21], *p1 = buf, *p2 = buf;
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
 
#endif
 
using namespace std;
struct ios{
    template<typename ATP>inline ios& operator >> (ATP &x){
        x = 0; int f = 1; char ch;
        for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
        while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ '0'), ch = getchar();
        x *= f;
        return *this;
    }
}io;
 
template<typename ATP>inline ATP Max(ATP a, ATP b){
    return a > b ? a : b;
}
template<typename ATP>inline ATP Min(ATP a, ATP b){
    return a < b ? a : b;
}
template<typename ATP>inline ATP Abs(ATP a){
    return a < 0 ? -a : a;
}

const int N = 50007;
const int M = 50007;

int n, S, T;
struct Edge{
	int nxt, pre, f;
}e[M];
int head[N], cntEdge = 1;
inline void add(int u, int v, int f){
	e[++cntEdge] = (Edge){ head[u], v, f}, head[u] = cntEdge;
}
inline void Add(int u, int v, int f){
	add(u, v, f);
	add(v, u, 0);
}
int vis[M];
int cur[N], q[N], d[N];
inline bool BFS(){
	int h = 0, t = 1;
	R(i,S,T) d[i] = -1;
	d[S] = 0, q[0] = S;
	while(h != t){
		int u = q[h++];
		if(h > 10000) h = 0; 
		for(register int i = head[u]; i; i = e[i].nxt){
			int v = e[i].pre;
			if(e[i].f && d[v] == -1){
				d[v] = d[u] + 1;
				q[t++] = e[i].pre;
				if(t > 10000) t = 0;
			}
		}
	}
	return d[T] != -1;
}
int nxt[N];
inline int DFS(int u, int f){
	if(u == T) return f;
	int flow, used = 0;
	for(register int i = cur[u]; i; i = e[i].nxt){
		cur[u] = i; 
		int v = e[i].pre;
		if(d[v] == d[u] + 1){
			flow = DFS(v, Min(f - used, e[i].f));
			if(flow){
				nxt[u] = v;
				if(v > n) vis[v - n] = 1;
			}
			e[i].f -= flow, e[i ^ 1].f += flow;
			used += flow;
			if(used == f) return f;
		}
	}
	if(!used) d[u] = -1;
	return used;
}
inline int Dinic(){
	int sum = 0;
	while(BFS()){
		R(i,S,T) cur[i] = head[i];
		sum += DFS(S, 0x7fffffff);
	}
	return sum;
}

int main(){
//FileOpen();
	int m;
	io >> n >> m;
	T = n << 1 | 1;
	R(i,1,n) Add(S, i, 1);
	R(i,1,n) Add(i + n, T, 1);
	R(i,1,m){
		int u, v;
		io >> u >> v;
		Add(u, v + n, 0x3f3f3f3f);
	}
	int ans = n - Dinic();
	R(i,1,n){
		if(vis[i]) continue;
		printf("%d ", i);
		register int j;
		for(j = i; nxt[j]; j = nxt[j] - n){
			printf("%d ", nxt[j] - n);
		}
		putchar('\n');
	}
    printf("%d",ans);
    return 0;
}

太空飞行计划问题

最大权闭合图

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); (a) <= (c); ++(a))
#define nR(a,b,c) for(register int a = (b); (a) >= (c); --(a))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ll long long
#define u32 unsigned int
#define u64 unsigned long long
 
#define ON_DEBUGG
 
#ifdef ON_DEBUGG
 
#define D_e_Line printf("\n----------\n")
#define D_e(x) cout << (#x) << " : " << x << endl
#define Pause() system("pause")
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#include <ctime>
#define TIME() fprintf(stderr, "\ntime: %.3fms\n", clock() * 1000.0 / CLOCKS_PER_SEC)

#else
 
#define D_e_Line ;
#define D_e(x) ;
#define Pause() ;
#define FileOpen() ;
#define FileSave() ;
#define TIME() ;
//char buf[1 << 21], *p1 = buf, *p2 = buf;
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
 
#endif
 
using namespace std;
struct ios{
    template<typename ATP>inline ios& operator >> (ATP &x){
        x = 0; int f = 1; char ch;
        for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
        while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ '0'), ch = getchar();
        x *= f;
        return *this;
    }
}io;
 
template<typename ATP>inline ATP Max(ATP a, ATP b){
    return a > b ? a : b;
}
template<typename ATP>inline ATP Min(ATP a, ATP b){
    return a < b ? a : b;
}
template<typename ATP>inline ATP Abs(ATP a){
    return a < 0 ? -a : a;
}

const int N = 20007;
const int M = 20007;

struct Edge{
	int nxt, pre, f;
}e[M];
int head[N], cntEdge = 1;
inline void add(int u, int v, int f){
	e[++cntEdge] = (Edge){ head[u], v, f}, head[u] = cntEdge;
}
inline void Add(int u, int v, int f){
	add(u, v, f);
	add(v, u, 0);
}
int n, m, S, T;
int cur[N], d[N], q[N];
inline bool BFS(){
	R(i,S,T) d[i] = -1;
	int h = 0, t = 1;
	d[S] = 0, q[h] = S;
	while(h != t){
		int u = q[h++];
		if(h > 10000) h = 0;
		for(register int i = head[u]; i; i = e[i].nxt){
			int v = e[i].pre;
			if(e[i].f && d[v] == -1){
				d[v] = d[u] + 1;
				q[t++] = v;
				if(t > 10000) t = 0;
			}
		}
	}
	return d[T] != -1;
}
inline int DFS(int u, int f){
	if(u == T) return f;
	int flow, used = 0;
	for(register int i = cur[u]; i; i = e[i].nxt){
		cur[u] = i;
		int v = e[i].pre;
		if(d[v] == d[u] + 1){
			flow = DFS(v, Min(e[i].f, f - used));
			e[i].f -= flow, e[i ^ 1].f += flow;
			used += flow;
			if(used == f) return f;
		}
	}
	if(!used) d[u] = -1;
	return used;
}
inline int Dinic(){
	int sum = 0;
	while(BFS()){
		R(i,S,T) cur[i] = head[i];
		sum += DFS(S, 0x7fffffff);
	}
	return sum;
}
inline bool read(int &x){
	x = 0; int f = 1; char ch;
	for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()){
		if(ch == '-')
			f = -1;
		else if(ch == '\n')
			return false;
	}
	while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ '0'), ch = getchar();
	x *= f;
	if(ch == '\n' || ch == '\r') return false;
	return true;
}
int main(){
//FileOpen();
	io >> m >> n;
	T = n + m + 1;
	int ans = 0;
	
	// S -> m -> n -> T
	
	R(i,1,m){
		int val;
		io >> val;
		Add(S, i, val);
		ans += val;
		int x;
		while(read(x)) Add(i, x + m, 0x3f3f3f3f);
		Add(i, x + m, 0x3f3f3f3f);
	}
	R(i,1,n){
		int val;
		io >> val;
		Add(i + m, T, val);
	}
	ans -= Dinic();
	R(i,1,m - 1){
		if(~d[i]){
			printf("%d ", i);
		}
	}
	if(~d[m]) printf("%d", m);
	putchar('\n');
	R(i,1,n - 1){
		if(~d[i + m]){
			printf("%d ", i);
		}
	}
	if(~d[n + m]) printf("%d", n);
	putchar('\n');
	printf("%d", ans);
	return 0;
}
/*
4 5
10 2 3
12 1
13 4
10 4 5
6 7 8 9 9
*/

圆桌问题

二分图多重匹配

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); (a) <= (c); ++(a))
#define nR(a,b,c) for(register int a = (b); (a) >= (c); --(a))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ll long long
#define u32 unsigned int
#define u64 unsigned long long
 
#define ON_DEBUGG
 
#ifdef ON_DEBUGG
 
#define D_e_Line printf("\n----------\n")
#define D_e(x) cout << (#x) << " : " << x << endl
#define Pause() system("pause")
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#include <ctime>
#define TIME() fprintf(stderr, "\ntime: %.3fms\n", clock() * 1000.0 / CLOCKS_PER_SEC)

#else
 
#define D_e_Line ;
#define D_e(x) ;
#define Pause() ;
#define FileOpen() ;
#define FileSave() ;
#define TIME() ;
//char buf[1 << 21], *p1 = buf, *p2 = buf;
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
 
#endif
 
using namespace std;
struct ios{
    template<typename ATP>inline ios& operator >> (ATP &x){
        x = 0; int f = 1; char ch;
        for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
        while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ '0'), ch = getchar();
        x *= f;
        return *this;
    }
}io;
 
template<typename ATP>inline ATP Max(ATP a, ATP b){
    return a > b ? a : b;
}
template<typename ATP>inline ATP Min(ATP a, ATP b){
    return a < b ? a : b;
}
template<typename ATP>inline ATP Abs(ATP a){
    return a < 0 ? -a : a;
}

const int N = 507;
const int M = 100007;

struct Edge{
	int nxt, pre, f;
}e[M];
int head[N], cntEdge = 1;
inline void add(int u, int v, int f){
	e[++cntEdge] = (Edge){ head[u], v, f}, head[u] = cntEdge;
}
inline void Add(int u, int v, int f){
	add(u, v, f);
	add(v, u, 0);
}

int n, m, S, T;
int cur[N], q[N], d[N];
inline bool BFS(){
	R(i,S,T) d[i] = -1;
	int t = 1, h = 0;
	q[h] = S, d[S] = 0;
	while(h != t){
		int u = q[h++];
		if(h > N - 5) h = 0;
		for(register int i = head[u]; i; i = e[i].nxt){
			int v = e[i].pre;
			if(e[i].f && d[v] == -1){
				d[v] = d[u] + 1;
				q[t++] = v;
				if(t > N - 5) t = 0;
			}
		}
	}
	return d[T] != -1;
}
inline int DFS(int u, int f){
	if(u == T) return f;
	int flow, used = 0;
	for(register int i = cur[u]; i; i = e[i].nxt){
		cur[u] = i;
		int v = e[i].pre;
		if(d[v] == d[u] + 1){
			flow = DFS(v, Min(f - used, e[i].f));
			e[i].f -= flow, e[i ^ 1].f += flow;
			used += flow;
			if(used == f) return f;
		}
	}
	if(!used) d[u] = -1;
	return used;
}
int ans;
inline void Dinic(){
	while(BFS()){
		R(i,S,T) cur[i] = head[i];
		ans += DFS(S, 0x7fffffff);
	}
}
int main(){
//FileOpen();
//FileSave();
	io >> m >> n;
	T = n + m + 1;
	int sum = 0;
	R(i,1,m){
		int x;
		io >> x;
		sum += x;
		Add(S, i, x);
	}
	R(i,1,n){
		int x;
		io >> x;
		Add(i + m, T, x);
	}
	R(i,1,m){
		R(j,1,n){
			Add(i,j + m, 1);
		}
	}
	Dinic();
	if(ans != sum){
		printf("0");
		return 0;
	}
	printf("1\n");
	R(u,1,m){
		for(register int i = head[u]; i; i = e[i].nxt){
			int v = e[i].pre;
			if(!e[i].f && v != S){
				printf("%d ", v - m);
			}
		}
		putchar('\n');
	}
	return 0;
}
/*
S ->  m ->  n  -> T 
*/

试题库问题

二分图多重匹配

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); (a) <= (c); ++(a))
#define nR(a,b,c) for(register int a = (b); (a) >= (c); --(a))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ll long long
#define u32 unsigned int
#define u64 unsigned long long
 
#define ON_DEBUGG
 
#ifdef ON_DEBUGG
 
#define D_e_Line printf("\n----------\n")
#define D_e(x) cout << (#x) << " : " << x << endl
#define Pause() system("pause")
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#include <ctime>
#define TIME() fprintf(stderr, "\ntime: %.3fms\n", clock() * 1000.0 / CLOCKS_PER_SEC)

#else
 
#define D_e_Line ;
#define D_e(x) ;
#define Pause() ;
#define FileOpen() ;
#define FileSave() ;
#define TIME() ;
//char buf[1 << 21], *p1 = buf, *p2 = buf;
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
 
#endif
 
using namespace std;
struct ios{
    template<typename ATP>inline ios& operator >> (ATP &x){
        x = 0; int f = 1; char ch;
        for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
        while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ '0'), ch = getchar();
        x *= f;
        return *this;
    }
}io;
 
template<typename ATP>inline ATP Max(ATP a, ATP b){
    return a > b ? a : b;
}
template<typename ATP>inline ATP Min(ATP a, ATP b){
    return a < b ? a : b;
}
template<typename ATP>inline ATP Abs(ATP a){
    return a < 0 ? -a : a;
}

const int N = 1007;
const int M = 1000007;

struct Edge{
	int nxt, pre, f;
}e[M];
int head[N], cntEdge = 1;
inline void add(int u, int v, int f){
	e[++cntEdge] = (Edge){ head[u], v, f}, head[u] = cntEdge;
}
inline void Add(int u, int v, int f){
	add(u, v, f);
	add(v, u, 0);
}

int n, m, S, T;
int cur[N], q[N], d[N]; 
inline bool BFS(){
	R(i,S,T) d[i] = -1;
	int t = 1, h = 0;
	d[S] = 0, q[0] = S;
	while(t != h){
		int u = q[h++];
		if(h > N - 5) h = 0;
		for(register int i = head[u]; i; i = e[i].nxt){
			int v = e[i].pre;
			if(e[i].f && d[v] == -1){
				d[v] = d[u] + 1;
				q[t++] = v;
				if(t > N - 5) t = 0;
			}
		}
	}
	return d[T] != -1;
}
inline int DFS(int u, int f){
	if(u == T) return f;
	int flow, used = 0;
	for(register int i= head[u]; i; i = e[i].nxt){
		int v = e[i].pre;
		if(d[v] == d[u] + 1){
			flow = DFS(v, Min(f - used, e[i].f));
			e[i].f -= flow, e[i ^ 1].f += flow;
			used += flow;
			if(used == f) return f;
		}
	}
	if(!used) d[u] = -1;
	return used;
}
int maxFlow;
inline void Dinic(){
	while(BFS()){
		R(i,S,T) cur[i] = head[i];
		maxFlow += DFS(S, 0x7fffffff);
	}
}
int main(){
	io >> m >> n; // m := k
	T = n + m + 1;
	int sum = 0;
	R(i,1,m){
		int x;
		io >> x;
		sum += x;
		Add(S, i, x);
	}
	R(i,1,n){
		int p;
		io >> p;
		while(p--){
			int x;
			io >> x;
			Add(x, i + m, 1);
		}
	}
	R(i,1,n){
		Add(i + m, T, 1);
	}
	Dinic();
	if(maxFlow != sum){
		printf("No Solution!");
		return 0;
	}
	R(u,1,m){
		printf("%d: ", u);
		for(register int i = head[u]; i; i = e[i].nxt){
			int v = e[i].pre;
			if(!e[i].f && v != S){
				printf("%d ", v - m);
			}
		}
		putchar('\n');
	}
	return 0;
}
/*
S -> m -> n -> T
*/

餐巾计划问题

线性规划网络优化

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); (a) <= (c); ++(a))
#define nR(a,b,c) for(register int a = (b); (a) >= (c); --(a))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ll long long
#define u32 unsigned int
#define u64 unsigned long long
 
#define ON_DEBUGG
 
#ifdef ON_DEBUGG
 
#define D_e_Line printf("\n----------\n")
#define D_e(x) cout << (#x) << " : " << x << endl
#define Pause() system("pause")
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#include <ctime>
#define TIME() fprintf(stderr, "\ntime: %.3fms\n", clock() * 1000.0 / CLOCKS_PER_SEC)

#else
 
#define D_e_Line ;
#define D_e(x) ;
#define Pause() ;
#define FileOpen() ;
#define FileSave() ;
#define TIME() ;
//char buf[1 << 21], *p1 = buf, *p2 = buf;
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
 
#endif
 
using namespace std;
struct ios{
    template<typename ATP>inline ios& operator >> (ATP &x){
        x = 0; int f = 1; char ch;
        for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
        while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ '0'), ch = getchar();
        x *= f;
        return *this;
    }
}io;
 
template<typename ATP>inline ATP Max(ATP a, ATP b){
    return a > b ? a : b;
}
template<typename ATP>inline ATP Min(ATP a, ATP b){
    return a < b ? a : b;
}
template<typename ATP>inline ATP Abs(ATP a){
    return a < 0 ? -a : a;
}

const int N = 4007;
const int M = 1000007;

struct Edge{
	int nxt, pre, from, f, w;
}e[M];
int head[N], cntEdge = 1;
inline void add(int u, int v, int f, int w){
	e[++cntEdge] = (Edge){ head[u], v, u, f, w}, head[u] = cntEdge;
}
inline void Add(int u, int v, int f, int w){
	add(u, v, f, w);
	add(v, u, 0, -w);
}

int n, S, T;
int q[N], from[N], vis[N];
long long dis[N];
inline bool SPFA(){
	R(i,S,T) dis[i] = 0x3f3f3f3f;
	int top = 1;
	dis[S] = 0, q[1] = S;
	while(top){
		int u = q[top--];
		vis[u] = false;
		for(register int i = head[u]; i; i = e[i].nxt){
			int v = e[i].pre;
			if(e[i].f && dis[v] > dis[u] + (long long)e[i].w){
				from[v] = i;
				dis[v] = dis[u] + (long long)e[i].w;
				if(!vis[v]){
					vis[v] = true;
					q[++top] = v;
				}
			}
		}
	}
	return dis[T] != 0x3f3f3f3f;
}
long long ans;
inline void MCMF(){
	int i = from[T], flow = 0x3f3f3f3f;
	while(i){
		flow = Min(flow, e[i].f);
		i = from[e[i].from];
	}
	i = from[T];
	while(i){
		ans += (long long)e[i].w * flow;
		e[i].f -= flow, e[i ^ 1].f += flow;
		i = from[e[i].from];
	}
}
int main(){
//FileOpen();
	io >> n;
	T = n << 1 | 1;
	R(i,1,n){
		int x;
		io >> x;
		Add(S, i + n, x, 0);
		Add(i, T, x, 0);
	}
	int price, fastDays, fastCost, slowDays, slowCost;
	io >> price >> fastDays >> fastCost >> slowDays >> slowCost;
	R(i,1,n){
		if(i + 1 <= n) Add(i + n, i + 1 + n, 0x3f3f3f3f, 0);
		if(i + slowDays <= n) Add(i + n, i + slowDays, 0x3f3f3f3f, slowCost);
		if(i + fastDays <= n) Add(i + n, i + fastDays, 0x3f3f3f3f, fastCost);
		Add(S, i, 0x3f3f3f3f, price);
	}
	while(SPFA()) MCMF();
	printf("%lld", ans);
	return 0;
}
/*
S -> i_1 -> i_2 -> T
*/

航空路线问题

航空路线问题

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
#define R(a,b,c) for(register int a = (b); (a) <= (c); ++(a))
#define nR(a,b,c) for(register int a = (b); (a) >= (c); --(a))
#define Fill(a,b) memset(a, b, sizeof(a))
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define ll long long
#define u32 unsigned int
#define u64 unsigned long long
 
#define ON_DEBUGG
 
#ifdef ON_DEBUGG
 
#define D_e_Line printf("\n----------\n")
#define D_e(x) cout << (#x) << " : " << x << endl
#define Pause() system("pause")
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#include <ctime>
#define TIME() fprintf(stderr, "\ntime: %.3fms\n", clock() * 1000.0 / CLOCKS_PER_SEC)

#else
 
#define D_e_Line ;
#define D_e(x) ;
#define Pause() ;
#define FileOpen() ;
#define FileSave() ;
#define TIME() ;
//char buf[1 << 21], *p1 = buf, *p2 = buf;
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
 
#endif
 
using namespace std;
struct ios{
    template<typename ATP>inline ios& operator >> (ATP &x){
        x = 0; int f = 1; char ch;
        for(ch = getchar(); ch < '0' || ch > '9'; ch = getchar()) if(ch == '-') f = -1;
        while(ch >= '0' && ch <= '9') x = x * 10 + (ch ^ '0'), ch = getchar();
        x *= f;
        return *this;
    }
}io;
 
template<typename ATP>inline ATP Max(ATP a, ATP b){
    return a > b ? a : b;
}
template<typename ATP>inline ATP Min(ATP a, ATP b){
    return a < b ? a : b;
}
template<typename ATP>inline ATP Abs(ATP a){
    return a < 0 ? -a : a;
}

const int N = 1007;
const int M = 1000007;

struct Edge{
	int nxt, pre, f, w;
}e[M];
int head[N], cntEdge = 1;
inline void add(int u, int v, int f, int w){
	e[++cntEdge] = (Edge){ head[u], v, f, w}, head[u] = cntEdge;
}
inline void Add(int u, int v, int f, int w){
	add(u, v, f, w);
	add(v, u, 0, -w);
}

int n, S, T;
int dis[N], vis[N], from[N], q[N];
inline bool SPFA(){
	R(i,S,T) dis[i] = 0x3f3f3f3f;
	int top = 1;
	dis[S] = 0, q[top] = S;
	while(top){
		int u = q[top--];
		vis[u] = false;
		for(register int i = head[u]; i; i = e[i].nxt){
			int v = e[i].pre;
			if(e[i].f && dis[v] > dis[u] + e[i].w){
				dis[v] = dis[u] + e[i].w;
				from[v] = i;
				if(!vis[v]){
					vis[v] = true;
					q[++top] = v;
				}
			}
		}
	}
	return dis[T] != 0x3f3f3f3f;
}
int ans, maxFlow;
inline void MCMF(){
	int i = from[T], flow = 0x3f3f3f3f;
	while(i){
		flow = Min(flow, e[i].f);
		i = from[e[i ^ 1].pre];
	}
	i = from[T];
	while(i){
		ans += e[i].w * flow;
		e[i].f -= flow, e[i ^ 1].f += flow;
		i = from[e[i ^ 1].pre];
	}
	maxFlow += flow;
}

namespace TRIE{
	
struct Trie{
	int ch[53], val;
}t[N];
int trieIndex;
inline void Add(char *str, int val){
	int rt = 0, len = strlen(str + 1);
	R(i,1,len){
		int k = str[i] - 'A';
		if(t[rt].ch[k] == 0) t[rt].ch[k] = ++trieIndex;
		rt = t[rt].ch[k];
	}
	t[rt].val = val;
}
inline int Find(char *str){
	int rt = 0, len = strlen(str + 1);
	R(i,1,len){
		int k = str[i] - 'A';
		rt = t[rt].ch[k];
	}
	return t[rt].val;
}
}
char name1[17], name2[17];
char str[N][17];
int main(){
//FileOpen();
	int m;
	io >> n >> m;
	S = 1, T = n << 1;
	R(i,1,n){
		scanf("%s", str[i] + 1);
		TRIE::Add(str[i], i);
		if(i != 1 && i != n)
			Add(i, i + n, 1, -1);
		else
			Add(i, i + n, 2, -1);
	}
	R(i,1,m){
		scanf("%s%s", name1 + 1, name2 + 1);
		int u = TRIE::Find(name1), v = TRIE::Find(name2);
		if(u > v) Swap(u, v);
		if(u != 1 || v != n)
			Add(u + n, v, 1, 0);
		else
			Add(u + n, v, 2, 0);
	}
	while(SPFA()) MCMF();
	if(maxFlow != 2){
		printf("No Solution!");
		return 0;
	}
	ans = -ans - 2;
	printf("%d\n", ans);
	
	vis[1] = vis[0] = 1;
	printf("%s\n", str[1] + 1);
	for(register int i = head[S + n]; i; i = e[i].nxt){
		int u = e[i].pre;
		if(!e[i].f && !vis[u]){
			while(!vis[u]){
				vis[u] = 1;
				printf("%s\n", str[u] + 1);
				for(register int j = head[u + n]; j; j = e[j].nxt){
					int v = e[j].pre;
					if(!e[j].f && !vis[v]){
						u = v;
						break;
					}
				}
			}
			break;
		}
	}
	for(register int i = head[n]; i; i = e[i].nxt){
		int u = e[i].pre;
		if(!e[i ^ 1].f && !vis[u - n]){
			u = u - n;
			while(!vis[u]){
				vis[u] = 1;
				printf("%s\n", str[u] + 1);
				for(register int j = head[u]; j; j = e[j].nxt){
					int v = e[j].pre;
					if(!e[j ^ 1].f && !vis[v - n]){
						u = v - n;
						break;
					}
				}
			}
			break;
		}
	}
	printf("%s\n", str[1] + 1);
	return 0;
}

没看的了,咕了

posted @ 2019-09-25 16:10  邱涵的秘密基地  阅读(106)  评论(0编辑  收藏  举报