UVA-11248 Frequency Hopping (最大流+最小割)

时间:2023-06-13 20:34:02

题目大意:给一张网络,问是否存在一条恰为C的流。若不存在,那是否存在一条弧,使得改动这条弧的容量后能恰有为C的流?

题目分析:先找出最大流,如果最大流不比C小,那么一定存在一条恰为C的流。否则,找出最小割集,然后枚举每一条弧改动其容量,看是否存在恰为C的流。

代码如下:

# include<iostream>
# include<cstdio>
# include<cmath>
# include<string>
# include<vector>
# include<list>
# include<set>
# include<map>
# include<queue>
# include<cstring>
# include<algorithm>
using namespace std; # define LL long long
# define REP(i,s,n) for(int i=s;i<n;++i)
# define CL(a,b) memset(a,b,sizeof(a))
# define CLL(a,b,n) fill(a,a+n,b) const double inf=1e30;
const int INF=1<<30;
const int maxn=10005; struct Edge
{
int fr,to;
LL cap,fw;
Edge(int _fr,int _to,LL _cap,LL _fw):fr(_fr),to(_to),cap(_cap),fw(_fw){}
bool operator <(const Edge &a) const{
if(fr==a.fr) return to<a.to;
return fr<a.fr;
}
};
vector<Edge>edges,tedges,ans;
vector<int>G[2*maxn];
vector<int>minCut;
int N,E,cur[105],vis[105],d[105];
LL C,Flow;
int s,t; void init()
{
Flow=0;
s=1,t=N;
edges.clear();
REP(i,0,N+1) G[i].clear();
} void addEdge(int u,int v,LL c)
{
edges.push_back(Edge(u,v,c,0));
edges.push_back(Edge(v,u,0,0));
int m=edges.size();
G[u].push_back(m-2);
G[v].push_back(m-1);
} bool BFS()
{
CL(vis,0);
queue<int>q;
vis[s]=1;
d[s]=0;
q.push(s);
while(!q.empty()){
int x=q.front();q.pop();
REP(i,0,G[x].size()){
Edge &e=edges[G[x][i]];
if(!vis[e.to]&&e.cap>e.fw){
vis[e.to]=1;
d[e.to]=d[x]+1;
q.push(e.to);
}
}
}
return vis[t];
} LL DFS(int x,LL a)
{
if(x==t||a==0) return a;
LL flow=0,f;
for(int &i=cur[x];i<G[x].size();++i){
Edge &e=edges[G[x][i]];
if(d[x]+1==d[e.to]&&(f=DFS(e.to,min(a,e.cap-e.fw)))>0){
e.fw+=f;
edges[G[x][i]^1].fw-=f;
flow+=f;
a-=f;
if(a==0) break;
}
}
return flow;
} bool Dinic()
{
while(BFS()){
CL(cur,0);
Flow+=DFS(s,INF);
if(Flow>=C) return true;
}
return false;
} void findCut()
{
minCut.clear();
for(int i=0;i<edges.size();i+=2){
Edge &e=edges[i];
if(vis[e.fr]&&!vis[e.to]) minCut.push_back(i);
}
} void toFind()
{
findCut();
ans.clear();
tedges.clear();
int len=edges.size();
REP(i,0,len) tedges.push_back(edges[i]);
LL f=Flow;
REP(i,0,minCut.size()){
edges[minCut[i]].cap+=C;
if(Dinic()) ans.push_back(edges[minCut[i]]);
Flow=f;
edges.clear();
REP(j,0,len) edges.push_back(tedges[j]);
}
} void solve(int cas)
{
printf("Case %d: ",cas);
if(C==0||Dinic()){
printf("possible\n");
}else{
toFind();
int len=ans.size();
if(len>0){
printf("possible option:");
sort(ans.begin(),ans.end());
REP(i,0,len) printf("(%d,%d)%c",ans[i].fr,ans[i].to,(i==len-1)?'\n':',');
}else
printf("not possible\n");
}
} void read()
{
int a,b;
LL c;
while(E--)
{
scanf("%d%d%lld",&a,&b,&c);
addEdge(a,b,c);
}
} int main()
{
int cas=0;
while(scanf("%d%d%lld",&N,&E,&C),N|E|C)
{
init();
read();
solve(++cas);
}
  return 0;
}