题目描述不多说了 总体来说比较简单 如果最大流大于c 直接possible 否则枚举最小割 将边容量增大为INF 再次检查最大流即可
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define MAXN 100
#define MAXM 10000
using namespace std;
typedef pair<int, int> pii;
pii A[MAXM+10];
vector <pii> ans;
const int INF = 0x3f3f3f3f;
int n, m, c;
template <int maxn, int maxm>
struct Isap
{
int ecnt;
int d[maxn+10], pre[maxn+10], cur[maxn+10], gap[maxn+10];
int adj[maxn+10];
struct node {
int v, next, c, f;
}Edge[maxm*2+10];
void init() { memset(adj, -1, sizeof(adj)); ecnt = 0; }
void addedge(int u, int v, int c)
{
Edge[ecnt].v = v;
Edge[ecnt].c = c;
Edge[ecnt].f = 0;
Edge[ecnt].next = adj[u];
adj[u] = ecnt++;
}
void add(int u, int v, int c)
{
addedge(u, v, c);
addedge(v, u, 0);
}
void init_dis(int t) // 据说单次意义不大的优化 多次小规模才会出现差距 仅仅是据说
{
queue <int> q;
memset(d, -1, sizeof(d));
memset(gap, 0, sizeof(gap));
d[t] = 0;
q.push(t);
while(!q.empty())
{
int u = q.front(); q.pop();
gap[d[u]]++;
for(int i = adj[u]; ~i; i = Edge[i].next)
{
int v = Edge[i].v;
if(d[v] == -1) { d[v] = d[u] + 1; q.push(v); }
}
}
}
int ISAP(int s, int t, int num)
{
init_dis(t);
int ans = 0, u = s;
int Flow = INF;
memcpy(cur, adj, sizeof(adj));
while(d[s] < num)
{
int &i = cur[u];
for(; ~i; i = Edge[i].next)
{
int v = Edge[i].v;
if(Edge[i].c > Edge[i].f && d[u] == d[v] + 1)
{
u = v;
pre[v] = i;
Flow = min(Flow, Edge[i].c - Edge[i].f);
if(u == t)
{
while(u != s) {
int j = pre[u];
Edge[j].f += Flow;
Edge[j^1].f -= Flow;
u = Edge[j^1].v;
}
ans += Flow;
Flow = INF;
}
break;
}
}
if(i == -1)
{
if(--gap[d[u]] == 0) break;
int dmin = num - 1;
cur[u] = adj[u];
for(int j = adj[u]; ~j; j = Edge[j].next) if(Edge[j].c > Edge[j].f) dmin = min(dmin, d[Edge[j].v]);
d[u] = dmin+1;
gap[d[u]]++;
if(u != s) u = Edge[pre[u]^1].v;
}
}
return ans;
}
};
Isap <MAXN+10, MAXM+10> sap, tmp;
int main()
{
int kase = 0;
while(scanf("%d%d%d", &n, &m, &c) == 3 && n)
{
kase++;
sap.init();
for(int i = 1; i <= m; i++)
{
int u, v, wt;
scanf("%d%d%d", &u, &v, &wt);
sap.add(u, v, wt);
A[i] = make_pair(u, v);
}
int Max_Flow = sap.ISAP(1, n, n);
printf("Case %d: ", kase);
if(Max_Flow >= c) {
printf("possible\n");
continue;
}
ans.clear();
memcpy(tmp.Edge, sap.Edge, sizeof(sap.Edge));
for(int i = 0; i < m; i++)
{
memcpy(sap.Edge, tmp.Edge, sizeof(sap.Edge));
if(sap.Edge[i*2].c == sap.Edge[i*2].f)
{
int u = A[i+1].first, v = A[i+1].second;
sap.Edge[i*2].c = INF;
int Flow = sap.ISAP(1, n, n);
Max_Flow += Flow;
if(Max_Flow >= c)
ans.push_back(make_pair(u, v));
Max_Flow -= Flow;
}
}
if(!ans.size()) {
printf("not possible\n");
continue;
}
sort(ans.begin(), ans.end());
printf("possible option:(%d,%d)", ans[0].first, ans[0].second);
for(int i = 1; i < ans.size(); i++) printf(",(%d,%d)", ans[i].first, ans[i].second);
puts("");
}
}
本文介绍了一种基于最大流算法的解决方案,通过实现ISAP算法来解决特定问题。该问题涉及判断是否可以通过调整某些边的最大容量使得从源点到汇点的最大流大于等于给定值c。若直接最大流满足条件,则输出possible;否则,尝试通过增加部分边的容量来达到目标。
6万+

被折叠的 条评论
为什么被折叠?



