pku 1815

求S--T的点割,把n个点拆成x + n --> x流量为1的点,其余在原图有的边流量为oo,然后求S到T的最大流,为了求点割,枚举每个除S,T之外的点比较流量是否减少,若减少则该点属于点割集,并把流量跟新,直到流量为0.

代码:

 

#include <stdio.h>
#include <string.h>
#define oo 0x7fffffff
#define MAXM 160002
#define MAXN 402
typedef struct
{
	int u; int v;
	int cap; int next;
}edge_t;
edge_t e[MAXM * 2];
int map[MAXN][MAXN];
int first[MAXN];
int stack[MAXN];
int dist[MAXN];
int now[MAXN];
int pre[MAXN];
int cnt[MAXN];
int cur[MAXN];
int cut[MAXN];
int top, tot, st, ed, n2, n;
void add(int u, int v, int cap)
{
	e[++tot].u = u; e[tot].v = v; e[tot].cap = cap; e[tot].next = first[u]; first[u] = tot;
	e[++tot].u = v; e[tot].v = u; e[tot].cap = 0;   e[tot].next = first[v]; first[v] = tot;
}
void init()
{
	int i, j, k;
	scanf("%d %d %d", &n, &st, &ed);
	for(i = 1;i <= n; i++)
	{
		for(j = 1;j <= n; j++) scanf("%d", &map[i][j]);
		map[i][i] = 0;
	}
	ed += n;
	n2 = n;
	n <<= 1;
}
void build()
{
	int i, j;
	memset(first, -1, sizeof(first));
	tot = -1;
	for(i = 1;i <= n2; i++)
	{
		add(n2 + i, i, 1 - cut[i]);
		for(j = 1;j <= n2; j++) if(map[i][j]) add(i, n2 + j, oo);
	}
}
int sap()
{
	int tot_flow;
	int now_flow, found, min;
	int i, j, t;
	memset(dist, 0, sizeof(dist));
	memset(now, -1, sizeof(now));
	memset(cnt, 0, sizeof(cnt));
	i = st;
	tot_flow = 0; now_flow = oo;
	cnt[0] = n;
	while(dist[st] < n)
	{
		cur[i] = now_flow; found = 0;
		if(now[i] == -1) t = first[i];
		else t = now[i];
		while(t != -1)
		{
			j = e[t].v;
			if(e[t].cap > 0 && dist[j] + 1 == dist[i])
			{
				found = 1; now[i] = t;
				if(e[t].cap < now_flow) now_flow = e[t].cap;
				pre[j] = t; i = j;
				if(i == ed)
				{
					tot_flow += now_flow;
					while(i != st)
					{
						e[pre[i]].cap -= now_flow;
						e[pre[i]^1].cap += now_flow;
						i = e[pre[i]].u;
					}
					now_flow = oo;
				}
				break;
			}
			t = e[t].next;
		}
		if(found) continue;
		if(--cnt[dist[i]] == 0) break;
		min = n - 1;
		t = first[i];
		while(t != -1)
		{
			if(e[t].cap > 0 && dist[e[t].v] < min)
			{
				min = dist[e[t].v];
				now[i] = t;
			}
			t = e[t].next;
		}
		dist[i] = min + 1;
		cnt[dist[i]]++;
		if(i != st)
		{
			i = e[pre[i]].u;
			now_flow = cur[i];
		}
	}
	return tot_flow;
}
int main()
{
	int maxflow, res, i;
	init();
	if(map[st][ed - n2] == 1) printf("NO ANSWER!\n");
	else
	{
		memset(cut, 0, sizeof(cut));
		build();
		maxflow = sap();
		if(maxflow == 0) printf("0\n");
		else
		{
			printf("%d\n", maxflow);
			top = 0;
			for(i = 1;i <= n2; i++)
			{
				if(i == st || i + n2 == ed) continue;
				cut[i] = 1;
				build();
				res = sap();
				if(res < maxflow)
				{
					stack[++top] = i;
					maxflow = res;
				}
				else cut[i] = 0;
				if(res == 0) break;
			}
			for(i = 1;i < top; i++) printf("%d ", stack[i]);
			printf("%d\n", stack[top]);
		}
	}
	return 0;
}

 

 

对待编程

尊重编程,热爱你写下的程序,他是的伙伴,而不是工具

PKU 2230 Watchcow

求1到1的双向欧拉路径,我把无向边拆成正向和反向的两条边,然后求1-1的欧拉回路,跑了1000+ms,好慢,呵呵。

代码:

 

#include <stdio.h>
#include <string.h>
#define MAXE 100002
#define MAXN 10002
typedef struct
{
	int u; int v; int next;
}edge_t;
edge_t e[MAXE];
char visited[MAXE];
int stack[MAXE];
int first[MAXN];
int top;
int tot;
int n;
void add(int u, int v)
{
	e[++tot].u = u; e[tot].v = v; e[tot].next = first[u]; first[u] = tot;
	e[++tot].u = v; e[tot].v = u; e[tot].next = first[v]; first[v] = tot;
}
void init()
{
	int n, m, u, v;
	scanf("%d %d", &n, &m);
	memset(first, -1, sizeof(first)); tot = -1;
	while(m--)
	{
		scanf("%d %d", &u, &v);
		add(u, v);
	}
}
void find_euler(int u)
{
	int t, v;
	t = first[u];
	while(t != -1)
	{
		v = e[t].v;
		if(visited[t] == 0)
		{
			visited[t] = 1;
			find_euler(v);
			stack[++top] = t;
		}
		t = e[t].next;
	}
}
int main()
{
	int i, k;
	init();
	memset(visited, 0, sizeof(visited));
	tot = 0;
	find_euler(1);
	k = -1;
	while(top > 0)
	{
		i = stack[top];
		if(k == e[i].u) printf("%d\n", e[i].v);
		else printf("%d\n%d\n", e[i].u, e[i].v);
		k = e[i].v;
		top--;
	}
	return 0;
}

 

 

pku 3614

我用网络流过了,呵呵,SAP很强大。

 

#include <stdio.h>
#include <string.h>
#define oo 0x7fffffff
#define MAXM 690000
#define MAXN 5003
typedef struct{int u; int v; int cap; int next;}edge_t;
edge_t e[MAXM * 2];
int first[MAXN];
int dist[MAXN];
int now[MAXN];
int pre[MAXN];
int cnt[MAXN];
int cur[MAXN];
int tot, n;
void add(int u, int v, int cap)
{
	e[++tot].u = u; e[tot].v = v; e[tot].cap = cap; e[tot].next = first[u]; first[u] = tot;
	e[++tot].u = v; e[tot].v = u; e[tot].cap = 0; e[tot].next = first[v]; first[v] = tot;
}
void init()
{
	int covers, spf, st, ed;
	int c, l, i, j;
	scanf("%d %d", &c, &l);
	for(i = 1;i <= c; i++) scanf("%d %d", &cnt[i], &cur[i]);
	memset(first, -1, sizeof(first)); tot = -1;
	st = 1;
	ed = c + l + 2;
	for(i = 1;i <= l; i++)
	{
		scanf("%d %d", &spf, &covers);
		add(st, i + 1, covers);
		for(j = 1;j <= c; j++) if(cnt[j] <= spf && spf <= cur[j]) add(i + 1, l + j + 1, oo);
	}
	for(i = 1;i <= c; i++) add(l + i + 1, ed, 1);
	n = ed;
}
int sap()
{
	int tot_flow;
	int now_flow, found, min;
	int st, ed, i, j, t;
	memset(dist, 0, sizeof(dist));
	memset(now, -1, sizeof(now));
	memset(cnt, 0, sizeof(cnt));
	st = 1; ed = n; i = st;
	tot_flow = 0; now_flow = oo;
	cnt[0] = n;
	while(dist[st] < n)
	{
		cur[i] = now_flow; found = 0;
		if(now[i] == -1) t = first[i];
		else t = now[i];
		while(t != -1)
		{
			j = e[t].v;
			if(e[t].cap > 0 && dist[j] + 1 == dist[i])
			{
				found = 1; now[i] = t;
				if(e[t].cap < now_flow) now_flow = e[t].cap;
				pre[j] = t; i = j;
				if(i == ed)
				{
					tot_flow += now_flow;
					while(i != st)
					{
						e[pre[i]].cap -= now_flow;
						e[pre[i]^1].cap += now_flow;
						i = e[pre[i]].u;
					}
					now_flow = oo;
				}
				break;
			}
			t = e[t].next;
		}
		if(found) continue;
		if(--cnt[dist[i]] == 0) break;
		min = n - 1;
		t = first[i];
		while(t != -1)
		{
			if(e[t].cap > 0 && dist[e[t].v] < min)
			{
				min = dist[e[t].v];
				now[i] = t;
			}
			t = e[t].next;
		}
		dist[i] = min + 1;
		cnt[dist[i]]++;
		if(i != st)
		{
			i = e[pre[i]].u;
			now_flow = cur[i];
		}
	}
	return tot_flow;
}
int main()
{
	int res;
	init();
	res = sap();
	printf("%d\n", res);
	return 0;
}

 

 

.emacs

开始使用emacs

先贴个.emacs

 

 

(setq indent-tabs-mode nil)
(setq default-tab-width 4)
(setq tab-width 4)
(setq tab-stop-list ())

;;set c program style
(add-hook 'c-mode-hook 'linux-c-mode)
(setq imenu-sort-function 'imenu--sort-by-name)
(defun linux-c-mode()
 (define-key c-mode-map [return] 'newline-and-indent)
 (interactive)
 (c-set-style "K&R")
 (c-toggle-hungry-state)
 (setq c-basic-offset 4)
 (imenu-add-menubar-index)
 (which-function-mode)
)
;;set cpp program style
(add-hook 'c++-mode-hook 'linux-cpp-mode)
(setq imenu-sort-function 'imenu--sort-by-name)
(defun linux-cpp-mode()
 (define-key c++-mode-map [return] 'newline-and-indent)
 (interactive)
  (c-set-style "K&R")
  (c-toggle-hungry-state)
 (setq c-basic-offset 4)
 (imenu-add-menubar-index)
 (which-function-mode)
)

;;关闭烦人的出错时的提示声。
(setq visible-bell t)

;;关闭起动时候的那个“开机画面”
(setq inhibit-startup-message t)

;;显示列号
(setq column-number-mode t)

;;高亮显示匹配的括号
(show-paren-mode 1)

;;光标靠近鼠标指针时,让鼠标指针自动让开,别挡住视线。
(mouse-avoidance-mode 'animate)

;;指针不闪,不恍花眼睛。
(blink-cursor-mode -1)
(transient-mark-mode 1)

;;语法加亮
(global-font-lock-mode t)

;;光标显示为一竖线
(setq-default cursor-type 'bar)

;; 不显示工具栏
(tool-bar-mode -1)

;;设置背景色和字体色
(set-foreground-color "grey")
(set-background-color "black")

;; 隐藏滚动条
(scroll-bar-mode -1)
;;滚动条在右侧
(set-scroll-bar-mode 'right)

;; 不产生备份文件,临时文件
(setq make-backup-files nil)
(setq-default make-backup-files nil)
;;关闭自动保存模式
(setq auto-save-mode nil)
;;关闭#filename#临时文件
(setq auto-save-default nil)

;; 支持emacs和外部程序的粘贴
(setq x-select-enable-clipboard t)

;; 给每行显示行号: http://stud4.tuwien.ac.at/~e0225855/linum/linum.html
(require 'linum)           
(global-linum-mode t)

(create-fontset-from-fontset-spec
 (concat
  "-*-DejaVu Sans Mono-medium-r-normal-*-14-*-*-*-*-*-fontset-courier,"))
 (set-default-font "fontset-courier")