UVa11248 Frequency Hopping(最大流+最小割)

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=33206

【思路】

       最大流最小割。

       可以确定的是如果不可行需要修改的是流量已经达到上限的最小割中的边。可以考虑依次修改求最大流。

       优化:1 在原最大流的基础上增广; 2 只增广到流量C为止。

【代码】

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<queue>
  4 #include<vector>
  5 #include<algorithm>
  6 using namespace std;
  7 
  8 const int maxn = 100+10;
  9 const int INF = 1e9*2+10;
 10 
 11 struct Edge{
 12     int u,v,cap,flow;
 13     bool operator<(const Edge& rhs) const{
 14         return u<rhs.u || (u==rhs.u && v<rhs.v) ;
 15     }
 16 };
 17 struct Dinic {
 18     int n,m,s,t;
 19     bool vis[maxn];
 20     int d[maxn],cur[maxn];
 21     vector<int> G[maxn];
 22     vector<Edge> es;
 23     
 24     void init(int n) {
 25         this->n=n;
 26         es.clear();
 27         for(int i=0;i<n;i++) G[i].clear();
 28     }
 29     void clearflow() {
 30         for(int i=0;i<es.size();i++) es[i].flow=0;
 31     }
 32     void AddEdge(int u,int v,int cap) {
 33         es.push_back((Edge){u,v,cap,0});
 34         es.push_back((Edge){v,u,0,0});
 35         m=es.size();
 36         G[u].push_back(m-2);
 37         G[v].push_back(m-1);
 38     }
 39     
 40     bool BFS() {
 41         queue<int> q;
 42         memset(vis,0,sizeof(vis));
 43         q.push(s); vis[s]=1; d[s]=0;
 44         while(!q.empty()) {
 45             int u=q.front(); q.pop();
 46             for(int i=0;i<G[u].size();i++) {
 47                 Edge& e=es[G[u][i]];
 48                 int v=e.v;
 49                 if(!vis[v] && e.cap>e.flow) {
 50                     vis[v]=1;
 51                     d[v]=d[u]+1;
 52                     q.push(v);
 53                 }
 54             }
 55         }
 56         return vis[t];
 57     }
 58     int DFS(int u,int a) {
 59         if(u==t || a==0) return a;
 60         int flow=0,f;
 61         for(int& i=cur[u];i<G[u].size();i++){
 62             Edge& e=es[G[u][i]];
 63             int v=e.v;
 64             if( d[v]==d[u]+1 && (f=DFS(v,min(a,e.cap-e.flow)))>0 ) {
 65                 e.flow+=f;
 66                 es[G[u][i]^1].flow-=f;
 67                 flow+=f,a-=f;
 68                 if(!a) break;
 69             }
 70         }
 71         return flow;
 72     }
 73     int Maxflow(int s,int t,int limit) {
 74         this->s=s , this->t=t;
 75         int flow=0;
 76         while(BFS() && flow<limit) {
 77             memset(cur,0,sizeof(cur));
 78             flow+=DFS(s,INF);
 79         }
 80         return flow;
 81     }
 82     vector<int> Mincut() {
 83         vector<int> ans;
 84         for(int i=0;i<es.size();i++)
 85             if(es[i].cap!=0 && es[i].cap==es[i].flow)
 86                  ans.push_back(i);
 87         return ans;
 88     }
 89     void reduce() {
 90         for(int i=0;i<es.size();i++) es[i].cap-=es[i].flow;
 91     }
 92 }dc;
 93 
 94 int n,m,C;
 95 
 96 int main() {
 97     int kase=0;
 98     while(scanf("%d%d%d",&n,&m,&C)==3 && n) {
 99         dc.init(n);
100         int u,v,w;
101         for(int i=0;i<m;i++) {
102             scanf("%d%d%d",&u,&v,&w);
103             u--,v--;
104             dc.AddEdge(u,v,w);
105         }
106         int flow=dc.Maxflow(0,n-1,INF);
107         printf("Case %d: ",++kase);
108         if(flow>=C) printf("possible
");
109         else {
110             vector<int> cut;
111             vector<Edge> ans;
112             cut=dc.Mincut();
113             dc.reduce();            //考虑除去最大流之后的剩余网络//即在原流基础上增广 
114             for(int i=0;i<cut.size();i++) {
115                 dc.clearflow();
116                 Edge& e=dc.es[cut[i]];
117                 int tmp=e.cap;
118                 e.cap=C;
119                 if(flow+dc.Maxflow(0,n-1,C-flow)>=C) ans.push_back(e);
120                 e.cap=tmp;
121             }
122             if(!ans.size()) printf("not possible
");
123             else {
124                 sort(ans.begin(),ans.end());
125                 printf("possible option:");
126                 int d=ans.size();
127                 for(int i=0;i<d-1;i++) printf("(%d,%d),",ans[i].u+1,ans[i].v+1); 
128                 printf("(%d,%d)
",ans[d-1].u+1,ans[d-1].v+1);
129             }
130         }
131     }
132     return 0;
133 }