版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37943488/article/details/81609050
题目链接:https://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2205
题目大意:给一个有向网络,每条边均有一个容量,问是否存在一个点从点1到点N,流量为C的流,如果不存在,是否可以恰好修改一条弧的容量,使得存在一条这样的流
这道题真的让我欲仙欲死,从天亮写到天黑
先求一次网络流,如果最大流已经大于等于C,那么就可以输出答案了,因为我可以调节流量使得最后流量为C。如果小于,那么我们增大的就要是最小割里的弧,为什么呢?因为最大流=最小割,所以我们通过修改最小割里的边来使得流量增大。所以求出最小割的边以后,我们先使得所有的边的容量减去这条边上的流量,因为已经没有用了。然后将C加在最小割的边的容量上,再跑一次最大流,如果满足了大于等于C,就说明可以通过调节这条边的容量使得最大流增大。并且没必要每一次都跑完最大流,只要大于等于C了即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<algorithm>
#include<set>
using namespace std;
typedef long long ll;
const int maxn=10010;
const int maxm=2e5+7;
const ll inf=0x3f3f3f3f3f3f3f3fll;
int n,m;
struct Node
{
int from;
int to;
ll capa;
ll flow;
int next;
}edge[maxm<<1];
int cnt;
ll C;
int head[maxn];
int dep[maxn];
int source,sink;
bool vis[maxn];
vector<int> vec;
vector<pair<int,int> > store;
void init()
{
memset(head,-1,sizeof(head));
store.clear();
cnt=0;
return;
}
void add(int u,int v,ll capa)
{
edge[cnt].from=u;
edge[cnt].to=v;
edge[cnt].capa=capa;
edge[cnt].flow=0;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].from=v;
edge[cnt].to=u;
edge[cnt].capa=0;
edge[cnt].flow=0;
edge[cnt].next=head[v];
head[v]=cnt++;
return;
}
bool bfs()
{
memset(dep,-1,sizeof(dep));
memset(vis,false,sizeof(vis));
vis[source]=true;
dep[source]=0;
queue<int> que;
que.push(source);
while(!que.empty())
{
int node=que.front();
que.pop();
for(int i=head[node];~i;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].capa>edge[i].flow&&dep[v]==-1)
{
dep[v]=dep[node]+1;
if(v==sink) return true;
if(!vis[v])
{
vis[v]=true;
que.push(v);
}
}
}
}
return dep[sink]!=-1;
}
ll dfs(int node,ll minn)
{
if(node==sink||minn==0)
{
return minn;
}
ll r=0;
for(int i=head[node];~i;i=edge[i].next)
{
int v=edge[i].to;
if(dep[v]==dep[node]+1)
{
ll tmp=dfs(v,min(minn,edge[i].capa-edge[i].flow));
if(tmp>0)
{
edge[i].flow+=tmp;
edge[i^1].flow-=tmp;
r+=tmp;
minn-=tmp;
if(!minn) break;
}
}
}
if(!r) dep[node]=-1;
return r;
}
ll dinic()
{
ll maxflow=0;
while(bfs())
{
maxflow+=dfs(source,inf);
if(maxflow>=C) break;
}
return maxflow;
}
void getcut()
{
bfs();
for(int i=1;i<=n;i++)
{
for(int j=head[i];~j;j=edge[j].next)
{
int u=edge[j].from;
int v=edge[j].to;
if(dep[u]!=-1&&dep[v]==-1&&edge[j].capa>0&&edge[j].capa==edge[j].flow)
{
vec.push_back(j);
}
}
}
return;
}
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ll cas=0;
while(~scanf("%d%d%lld",&n,&m,&C))
{
init();
if(!n&&!m&&!C) break;
for(int i=0;i<m;i++)
{
int u,v;
ll w;
scanf("%d%d%lld",&u,&v,&w);
add(u,v,w);
}
source=1;
sink=n;
ll ans=dinic();
if(ans>=C||C==0)
{
printf("Case %lld: possible\n",++cas);
}
else
{
vec.clear();
se.clear();
getcut();
for(int i=1;i<=n;i++)
{
for(int j=head[i];~j;j=edge[j].next)
{
edge[j].capa-=edge[j].flow;
}
}
int len=vec.size();
for(int i=0;i<len;i++)
{
for(int j=1;j<=n;j++)
{
for(int k=head[j];~k;k=edge[k].next)
{
edge[k].flow=0;
}
}
int index=vec[i];
edge[index].capa+=C;
if(ans+dinic()>=C)
{
store.push_back(make_pair(edge[index].from,edge[index].to));
}
edge[index].capa-=C;
}
if(store.empty())
{
printf("Case %lld: not possible\n", ++cas);
}
else
{
sort(store.begin(),store.end());
printf("Case %lld: possible option:(%d,%d)",++cas,store[0].first,store[0].second);
int lenlen=store.size();
for(int i=1;i<lenlen;i++)
{
printf(",(%d,%d)",store[i].first,store[i].second);
}
puts("");
}
}
}
return 0;
}