一道经典的01分数规划问题,相关知识请看《最小割模型论文》。上面有完整的证明和解释。
/***************************************** Author :Crazy_AC(JamesQi) Time :2016 File Name : *****************************************/ // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <iostream> #include <algorithm> #include <iomanip> #include <sstream> #include <string> #include <stack> #include <queue> #include <deque> #include <vector> #include <map> #include <set> #include <cstdio> #include <cstring> #include <cmath> #include <cstdlib> #include <climits> using namespace std; #define MEM(x,y) memset(x, y,sizeof x) #define pk push_back typedef long long LL; typedef unsigned long long ULL; typedef pair<int,int> ii; typedef pair<ii,int> iii; const double eps = 1e-6; const int inf = 1 << 30; const int INF = 0x3f3f3f3f; const int MOD = 1e9 + 7; const int maxn = 110; const int maxm = 1010; struct Edge { int from, to, nxt; double cap; Edge(){} Edge(int from,int to,double cap,int nxt) : from(from), to(to), cap(cap), nxt(nxt) {} }edges[maxm]; int head[maxn], ecnt; bool vis[maxn]; int dis[maxn]; bool spfa(int s,int t) { memset(dis, -1,sizeof dis); queue<int> que; dis[s] = 0; que.push(s); while(!que.empty()) { int u = que.front(); que.pop(); for (int i = head[u];~i;i = edges[i].nxt) { Edge& e = edges[i]; if (e.cap > 0 && dis[e.to] == -1) { dis[e.to] = dis[u] + 1; que.push(e.to); } } } return dis[t] != -1; } int s, t; double dfs(int u,double a) { if (u == t || a == 0) return a; double flow = 0, f; for (int i = head[u];~i;i=edges[i].nxt) { Edge& e = edges[i]; if (dis[e.to] == dis[u] + 1 && (f = dfs(e.to, min(a, e.cap))) > 0) { flow += f; a -= f; e.cap -= f; edges[i^1].cap += f; return f; if (a <= 0) break; } } return flow; } double Dinic(int s,int t) { double ret = 0; while(spfa(s, t)) { ret += dfs(s, INF); // cout << "wocao\n"; } return ret;//ret >= 0; } struct Item { int from, to; double cap; }p[maxm]; int n, m; double Getmap(double mid) { double sum = 0; ecnt = 0; memset(head, -1,sizeof head); for (int i = 1;i <= m;++i) { if (p[i].cap > mid) { edges[ecnt] = Edge(p[i].from, p[i].to, p[i].cap - mid, head[p[i].from]); head[p[i].from] = ecnt++; edges[ecnt] = Edge(p[i].to, p[i].from, p[i].cap - mid, head[p[i].to]); head[p[i].to] = ecnt++; }else sum += (p[i].cap - mid); } return sum;//sum <= 0; } // void search(int u) { // vis[u] = true; // for (int i = head[u];~i;i=edges[i].nxt) { // Edge& e = edges[i]; // if (e.cap > 0 && !vis[e.to]) { // search(e.to); // } // } // } void bfs(int s) { queue<int> que; que.push(s); vis[s] = true; while(!que.empty()) { int u = que.front();que.pop(); for (int i = head[u];~i;i=edges[i].nxt) { Edge& e = edges[i]; if (e.cap > 0 && !vis[e.to]) { vis[e.to] = true; que.push(e.to); } } } } int main() { // freopen("in.txt","r",stdin); // freopen("out.txt","w",stdout); int first =1; while(~scanf("%d%d",&n,&m)) { double low = INF, high = -INF; for (int i = 1;i <= m;++i) { scanf("%d%d%lf",&p[i].from,&p[i].to,&p[i].cap); low = min(low, p[i].cap); high = max(high, p[i].cap); } s = 1, t = n; double mid; while(high - low > eps) { mid = (high + low) / 2.0; if (Getmap(mid) + Dinic(s, t) > eps) low = mid; else high = mid; } memset(vis, false,sizeof vis); bfs(1); // search(1); vector<int> vec; for (int i = 1;i <= m;++i) { if (vis[p[i].from] + vis[p[i].to] == 1 || p[i].cap <= mid) vec.push_back(i); } int size = (int)vec.size(); if (!first) puts(""); first = 0; printf("%d\n", size); for (int i = 0;i < size - 1;++i) printf("%d ", vec[i]); printf("%d\n", vec[size - 1]); } return 0; }