zoj 2676 最小割+0-1规划 ***

链接:点我

 

  1 #include <iostream>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <string>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <queue>
  8 #include <map>
  9 #include <set>
 10 #define eps 1e-5
 11 #define MAXN 222
 12 #define MAXM 5555
 13 #define INF 100000007
 14 using namespace std;
 15 typedef double type;
 16 struct node
 17 {
 18     int v;
 19     type c, f;
 20     int next, r; 
 21 }edge[MAXM];
 22 int dist[MAXN], nm[MAXN], src, des, n;
 23 int head[MAXN], e;
 24 void add(int x, int y, type c)
 25 {
 26     edge[e].v = y;
 27     edge[e].c = c;
 28     edge[e].f = 0;
 29     edge[e].r = e + 1;
 30     edge[e].next = head[x];
 31     head[x] = e++;
 32     edge[e].v = x;
 33     edge[e].c = 0;
 34     edge[e].f = 0;
 35     edge[e].r = e - 1;
 36     edge[e].next = head[y];
 37     head[y] = e++;
 38 }
 39 void rev_BFS()
 40 {
 41     int Q[MAXN], h = 0, t = 0;
 42     for(int i = 1; i <= n; ++i)
 43     {
 44         dist[i] = MAXN;
 45         nm[i] = 0;
 46     }
 47     Q[t++] = des;
 48     dist[des] = 0;
 49     nm[0] = 1;
 50     while(h != t)
 51     {
 52         int v = Q[h++];
 53         for(int i = head[v]; i != -1; i = edge[i].next)
 54         {
 55             if(edge[edge[i].r].c == 0 || dist[edge[i].v] < MAXN)continue;
 56             dist[edge[i].v] = dist[v] + 1;
 57             ++nm[dist[edge[i].v]];
 58             Q[t++] = edge[i].v;
 59         }
 60     }
 61 }
 62 void init()
 63 {
 64     e = 0;
 65     memset(head, -1, sizeof(head));
 66 }
 67 type maxflow()
 68 {
 69     rev_BFS();
 70     int u;
 71     type total = 0;
 72     int cur[MAXN], rpath[MAXN];
 73     for(int i = 1; i <= n; ++i)cur[i] = head[i];
 74     u = src;
 75     while(dist[src] < n)
 76     {
 77         if(u == des)     // find an augmenting path
 78         {
 79             type tf = INF;
 80             for(int i = src; i != des; i = edge[cur[i]].v)
 81                 tf = min(tf, edge[cur[i]].c);
 82             for(int i = src; i != des; i = edge[cur[i]].v)
 83             {
 84                 edge[cur[i]].c -= tf;
 85                 edge[edge[cur[i]].r].c += tf;
 86                 edge[cur[i]].f += tf;
 87                 edge[edge[cur[i]].r].f -= tf;
 88             }
 89             total += tf;
 90             u = src;
 91         }
 92         int i;
 93         for(i = cur[u]; i != -1; i = edge[i].next)
 94             if(edge[i].c > 0 && dist[u] == dist[edge[i].v] + 1)break;
 95         if(i != -1)     // find an admissible arc, then Advance
 96         {
 97             cur[u] = i;
 98             rpath[edge[i].v] = edge[i].r;
 99             u = edge[i].v;
100         }
101         else        // no admissible arc, then relabel this vtex
102         {
103             if(0 == (--nm[dist[u]]))break;    // GAP cut, Important!
104             cur[u] = head[u];
105             int mindist = n;
106             for(int j = head[u]; j != -1; j = edge[j].next)
107                 if(edge[j].c > 0)mindist = min(mindist, dist[edge[j].v]);
108             dist[u] = mindist + 1;
109             ++nm[dist[u]];
110             if(u != src)
111                 u = edge[rpath[u]].v;    // Backtrack
112         }
113     }
114     return total;
115 }
116 int nt, m;
117 int xx[MAXM], yy[MAXM], vis[MAXN], out[MAXM];
118 type cc[MAXM];
119 bool ok(double mid)
120 {
121     init();
122     double flow = 0;
123     for(int i = 1; i <= m; i++)
124     {
125         if(cc[i] > mid)
126             add(xx[i], yy[i], cc[i] - mid), add(yy[i], xx[i], cc[i] - mid);
127         else flow += cc[i] - mid;
128     }
129     flow += maxflow();
130     if(flow < eps) return true;
131     else return false;
132 }
133 void dfs(int u)
134 {
135     vis[u] = 1;
136     for(int i = head[u]; i != -1; i = edge[i].next)
137         if(edge[i].c > 0 && !vis[edge[i].v])
138             dfs(edge[i].v);
139 }
140 int main()
141 {
142     int cas = 0;
143     while(scanf("%d%d", &nt, &m) != EOF)
144     {
145         if(cas++) printf("\n");
146         src = 1;
147         des = nt;
148         n = nt;
149         double low = INF, high = 0;
150         for(int i = 1; i <= m; i++)
151         {
152             scanf("%d%d%lf", &xx[i], &yy[i], &cc[i]);
153             low = min(low, cc[i]);
154             high = max(high, cc[i]);
155         }
156         while(high - low > eps)
157         {
158             double mid = (low + high) / 2;
159             if(ok(mid)) high = mid;
160             else low = mid;
161         }
162         ok(low);
163         memset(vis, 0, sizeof(vis));
164         dfs(src);
165         int cnt = 0;
166         for(int i = 1; i <= m; i++)
167             if(vis[xx[i]] + vis[yy[i]] == 1 || cc[i] <= low)
168                 out[cnt++] = i;
169         printf("%d\n", cnt);
170         for(int i = 0; i < cnt; i++)
171         {
172             printf("%d", out[i]);
173             if(i < cnt - 1) putchar(' ');
174             else putchar('\n');
175         }
176     }
177     return 0;
178 }
2015/5/28

 

posted @ 2015-06-01 00:02  miao_a_miao  阅读(111)  评论(0编辑  收藏  举报