题目链接: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 }

 

posted on 2012-12-07 14:48  pony1993  阅读(746)  评论(0编辑  收藏  举报

View My Stats