题目链接:http://poj.org/problem?id=3436
纠结了好几天的题目,看懂题意就看了好长时间,题目大意:
有N台机器,每台机器有P部分,每部分有自己的输入、输出,因此每台机器有2*P+1种参数:第一个参数Q:该机器的容量;接下来P个参数S:该机器各部分的输入;接下来P个参数D:该机器各部分的输出。
其中输入有三种情况:0,1,2
0:该部分必须不要;1:该部分必须要;2:该部分可有可无
输出有2种情况:0,1
0:该部分不存在;1:该部分存在
题目要求的是最大流、流量改变的边数和改变的边。
思路:
如果某个节点 u 的输入部分没有1,则添加一条 s->u 路径,容量为Qu;如果某个节点 v 输出全为1,则添加一条 v->t 路径,容量为Qv;如果节点 u 的输出与 v 的输入不冲突,则添加一条 u->v 的路径,容量为min(Qu, Qv)。
看了一下网上的题解,基本上都是用拆点建图过的,不知道为什么,按照我的这个思路,没拆点也过了,可能数据弱?
代码:
1 const int maxn = 110; 2 const int maxm = 20500; 3 const int oo = 1<<29; 4 struct edge{ 5 int u; 6 int v; 7 int w; 8 int next; 9 edge(){ 10 w = 0; 11 } 12 }edge[maxn], edge1[maxn]; 13 int n, cnt; 14 int head[maxn], dep[maxn], gap[maxn]; 15 int s[maxn], cur[maxn], head1[maxn]; 16 17 void add(int u, int v, int w){ 18 edge[cnt].u = u; 19 edge[cnt].v = v; 20 edge[cnt].w = w; 21 edge[cnt].next = head[u]; 22 edge1[cnt].u = u; 23 edge1[cnt].v = v; 24 edge1[cnt].w = w; 25 edge1[cnt].next = head[u]; 26 head[u] = cnt++; 27 head1[u] = cnt - 1; 28 edge[cnt].u = v; 29 edge[cnt].v = u; 30 edge[cnt].w = 0; 31 edge1[cnt].u = v; 32 edge1[cnt].v = u; 33 edge1[cnt].w = 0; 34 edge1[cnt].next = head[v]; 35 edge[cnt].next = head[v]; 36 head[v] = cnt++; 37 head1[v] = cnt - 1; 38 } 39 40 void BFS(int start, int end){ 41 int i, to, u; 42 memset(dep, -1, sizeof(dep)); 43 memset(gap, 0, sizeof(gap)); 44 queue <int> que; 45 dep[end] = 0; 46 gap[0] = 1; 47 que.push(end); 48 while(!que.empty()){ 49 u = que.front(); 50 que.pop(); 51 for(i = head[u]; i != -1; i = edge[i].next){ 52 to = edge[i].v; 53 if(dep[to] != -1 || edge[i].w != 0) continue; 54 que.push(to); 55 dep[to] = dep[u]+1; 56 gap[dep[to]]++; 57 } 58 } 59 } 60 61 int sap(int start, int end){ 62 int res = 0; 63 BFS(start, end); 64 int u = start, top = 0; 65 memcpy(cur, head, sizeof(head)); 66 while(dep[start] < n){ 67 if(u == end){ 68 int Min = oo, flag; 69 for(int i = 0; i < top; i++){ 70 if(edge[s[i]].w < Min){ 71 Min = edge[s[i]].w; 72 flag = i; 73 } 74 } 75 res += Min; 76 for(int i = 0; i < top; i++){ 77 edge[s[i]].w -= Min; 78 edge[s[i]^1].w += Min; 79 } 80 top = flag; 81 u = edge[s[top]].u; 82 } 83 if(u != end && gap[dep[u]-1] == 0) break; 84 int i; 85 for(i = cur[u]; i != -1; i = edge[i].next){ 86 if(edge[i].w != 0 && dep[edge[i].v]+1 == dep[u]) break; 87 } 88 if(i != -1){ 89 cur[u] = i; 90 s[top++] = i; 91 u = edge[i].v; 92 } 93 else{ 94 int Min = n; 95 for(i = head[u]; i != -1; i = edge[i].next){ 96 if(edge[i].w == 0) continue; 97 if(Min > dep[edge[i].v]){ 98 cur[u] = i; 99 Min = dep[edge[i].v]; 100 } 101 } 102 gap[dep[u]]--; 103 dep[u] = Min+1; 104 gap[dep[u]]++; 105 if(u != start) 106 u = edge[s[--top]].u; 107 } 108 } 109 return res; 110 } 111 112 void init(){ 113 cnt = 0; 114 memset(head, -1, sizeof(head)); 115 } 116 117 int main(){ 118 #ifndef ONLINE_JUDGE 119 freopen("in.txt", "r", stdin); 120 //freopen("out.txt", "w", stdout); 121 #endif 122 int p; 123 int a[maxn], s[maxn][maxn], q[maxn][maxn]; 124 while(~scanf("%d %d", &p, &n)){ 125 init(); 126 int pr[101][3]; 127 int start , end; 128 start = 0; 129 end = n+1; 130 for(int i = 1; i <= n; i++){ 131 scan_d(a[i]); 132 for(int j = 0; j < p; j++){ 133 scan_d(s[i][j]); 134 } 135 for(int j = 0; j < p; j++){ 136 scan_d(q[i][j]); 137 } 138 } 139 for(int i = 1; i <= n; i++){ 140 bool fs = true, ft = true; 141 for(int j = 0; j < p; j++){ 142 if(s[i][j] == 1) fs = false; 143 if(q[i][j] == 0) ft = false; 144 } 145 if(fs) { 146 //printf("%d %d %d\n", start, i, a[i]); 147 add(start, i, a[i]); 148 } 149 if(ft){ 150 //printf("%d %d %d\n", i, end, a[i]); 151 add(i, end, a[i]); 152 } 153 bool fc = true; 154 for(int j = 1; j <= n; j++){ 155 if(i != j){ 156 fc = true; 157 for(int k = 0; k < p && fc; k++){ 158 if(q[i][k] + s[j][k] == 1) fc = false; 159 } 160 if(fc){ 161 //printf("%d %d %d\n", i, j, min(a[i], a[j])); 162 add(i, j, min(a[i], a[j])); 163 } 164 } 165 } 166 } 167 n += 2; 168 int res = sap(start, end); 169 //cout << res << endl; 170 int numb = 0; 171 for(int i = 0; i <= cnt; i++){ 172 if(edge[i].w < edge1[i].w && edge[i].u!=0 && edge[i].v!=n-1){ 173 pr[numb][0] = edge[i].u; 174 pr[numb][1] = edge[i].v; 175 pr[numb++][2] = edge1[i].w - edge[i].w; 176 } 177 } 178 printf("%d %d\n", res, numb); 179 for(int i = 0; i < numb; i++){ 180 printf("%d %d %d\n", pr[i][0], pr[i][1], pr[i][2]); 181 } 182 } 183 return 0; 184 }