System of difference constraints

Problem Description


Given Some inequality on some variable (Xi , Xj , …. ) in form
Xj – Xi <= W
We need to determine whether we can assign values to variables so that all the given inequality is satisfiable or not ? If satisfiable, then output A solution.

This System is called System of difference constraints. This is a special case of linear programming and yet very much useful.

Solution

Believe it or not, This problem has an elegant solution using Shortest Path algorithm.
To understand Please go through this :
1. lec18
2. Introduction To Algorithm (3rd Edition) : 24.4 Section

So I am writing the results (no proof). Proofs are discussed in details in the suggested readings.

Constraint Graph


– For each variable we create a vertex.
– For each in-equality, Xj – Xi <= W , We give an edge (Vi,Vj) with cost W
haha
– Create a source vertex (S) and give an edge (S,Vi) with cost = 0 ( Without using source vertex,we can solve)

Example:
Finding values for the unknowns x1,x2,x3,x4,x5, satisfying the following 8 difference constraints
example

Constraint Graph with Solutions:
bel

Unsatisfiable constraints


Theorem. If the constraint graph contains a negative-weight cycle, then the system of differences is unsatisfiable.
Proof is given in the pdf file.

Now we know if there is a solution or not.

Determining a Possible Solution :


– If there is no negative cycle in the constraint graph, Then There is a solution for the system. One of the solution is
for each variable (Xi):
Xi = Shortest Path distance of Vi from the Source vertex in Constraint Graph.
What about other solutions???
Let x = {x1,x2,…, xn } be a solution to a system of difference con- straints, and let d be any constant. Then x + d = { x1 + d, x2 + d, . . . , xn + d } is a solution as well.

Shortest Path can be calculated from Bellman-Ford algorithm.
Other Results from The constraint Graph:
# Bellman-Ford maximizes x1 + x2 + …. + xn subject to the constraints xj – xi ≤ wij and xi ≤ 0
# Bellman-Ford also minimizes maximum{xi} – minimum {xi}

Practise Problem:
1. Uva 11478

Solution:
For each node v in the given graph, Create a variable D_v such that we have operated Halum (v,D_v ) on the vertex v.
We then Binary Search on the answer.
Let Ans = X. We need to determine is X can possibly be our answer.
for each edge (u,v) , We get,
D_u - D_v + cost  of  the  edge >= X
=> D_v - D_u <= cost - X

This is just difference constraint discussed above. We can check whether we can satisfy all these conditions.

Lastly output the maximal answer.

Click to See Code

#include <bits/stdc++.h>
using namespace std;

struct Edge{
    int u,v,w;
};
vector<Edge>edge;
int n,e,u,v,w;
vector<pair<int,int > >G[505];

int d[505];
bool inq[505];
int Times[505];


bool spfa()
{
    queue<int>q;   // I have omitted Source vertex by pushing all the variables in queue with distance = 0
    for(int i = 1;i <= n; i ++ ) {
        d[i]= 0;
        q.push(i);
        inq[i] = 1;
        Times[i] = 1;
    }
    
    while(!q.empty()){
        int u = q.front(); q.pop();
        inq[u] = 0;
        for(int i = 0; i < G[u].size(); i ++ ) {
            int v = G[u][i].first, w = G[u][i].second;
            if(d[v] > d[u] + w) {
                d[v] = d[u]  + w;
                if(inq[v] == 0) {
                    inq[v] = 1;
                    q.push(v);
                    Times[v] ++;
                    
                    if(Times[v] > n+2 ) return 0;
                }
                
            }
        }
    }
    return 1;
}
bool can(int Mid)
{
    for(int i = 0; i <= n; i ++ ) {
        G[i].clear();
    }
    
    for(int i = 0; i < e; i ++ ) {
        u = edge[i].u, v = edge[i].v  , w = edge[i].w ;
        G[u].push_back(make_pair(v,w - Mid));
    }
    
    return spfa();
}
int main()
{
    while(scanf("%d %d",&n,&e)==2) {
        edge.clear();
        for(int i = 0; i < e; i ++ ) {
            scanf("%d %d %d",&u,&v,&w);
            edge.push_back({u,v,w});
        }
        if(can(10001)) {
            printf("Infinite\n");
            continue;
        }
        int low = 1, high = 10000, mid, ans = -1;
        while(low <= high ) {
            mid = (low+high) /2;
            if(can(mid)) {
                ans = mid;
                low  = mid+1;
            }
            else high= mid-1;
        }
        if(ans == -1 ) printf("No Solution\n");
        else printf("%d\n",ans);
        edge.clear();
    }
}


2. Uva 515 – King
3. POJ – 1201
4. POJ – 2983
5. POJ 1275
6. POJ – 3159
7. POJ – 3169

ONBRIDGE – Online Bridge Searching

Category : Graph, Bridges
Problem Link : ONBRIDGE

Problem Description: Given a empty undirected graph with n nodes. Then a list of m edges, output the number of bridges in the graph after adding each edge.

Solution:
Normally, We can calculate bridges in a graph in O(n+m). But for each each edge, we can not do the following.In that case complexity will be O(n+m) * m, which is large.
To solve this problem We should know about Biconnected Component(BCC)\

To know about BCC, I can refer https://en.wikipedia.org/wiki/Biconnected_component
But simply, BCC is a collection of nodes, Where there are more than one path from any node to another node.In other words, a bcc doesn’t contain any bridges. They are simply cycles.

Again, What is Connected Components?
Connected Components is a set of nodes, where there is atleast a path from each node to other node.
I think these definition is enough to understand the solution.

Claim: In a undirected graph, A connected components forms a tree where nodes are BCC.(Think ? )
unnamed0
We are going to add edges one by one and calculate the bridges.

Lets add a-b edge:
Three case may occur.

Case 1.

a and b in same BCC. like adding a edge between 2 and 3.
because this two nodes are already in same bcc, this doesn’t add any bridge or reduces # of bridges.

Case 2.

if a and b are in two different connected component.
This edge is a bridge edge because adding this edge decreases the number of connected components.
bridges get increased by 1.
Now we need to merge this two connected components according to their respective size. This ensures O(1) running time.
Let’s see an example:
unnamed1
without loss of generality, Lets assume a is in small connected component. What we need to do is make a as a root of his connected component. This is done going towards its parent ans reversing the link.
Finally Link a to b.
unnamed2

Case 3.

If a and b is in same connected component. So there is a cycle formed in the tree. So we need to traverse the cycle and compress all the nodes in a BCC.

Lets see an example:

unnamed3
So all the tree edges in this components were bridges earlier. So we cancel them out.
This is done by finding the lca then traverse trough all the nodes on the path. Make them in the same bcc.

Here is The solution:
unnamed4

My code :

#include<bits/stdc++.h>
using namespace std;

const int N = 5e4+4;
int n,bridge,m;
int bcc[N],comp[N], link[N],SZ[N];
void init()
{
    for(int i = 0;i < n; i ++ ){
        bcc[i] = comp[i] = i;   // BCC and CC of a node, Initially all are isolate.
        link[i] = -1;           // Link to the parent in a CC
        SZ[i] = 1;              // Size of a CC 
    }
    bridge = 0;
}
// Output the BCC of a node
int getBCC(int a)
{
    if(a==-1)return -1;
    if(bcc[a]==a) return a;
    else return bcc[a] = getBCC(bcc[a]);
}
// Output the root of the component where a is.
int getCOMP(int a)
{
    if(comp[a]==a) return a;
    else return comp[a] = getCOMP(comp[a]);
}
// Merging two path, a->lca, b->lca.
int cs = 0, vis[N];
void MergePath(int a,int b)
{
    cs++;
    a = getBCC(a);
    b = getBCC(b);
    vector<int> va,vb;
    int lca = -1;
    while(1) {
        if(a!=-1) {
            a = getBCC(a);
            va.push_back(a);
            if(vis[a] == cs) {
                lca = a;
                break;
            }
            vis[a] = cs;
            a = link[a];
        }
        if(b!=-1) {
            b = getBCC(b);
            vb.push_back(b);
            if(vis[b]==cs) {
                lca = b;
                break;
            }
            vis[b] = cs;
            b = link[b];
        }
    }
    for(int i = 0;i < va.size();i  ++) {
        bcc[va[i]] = lca;   // Compressing in same BCC
        if(va[i]==lca) break;
        bridge --;
    }
    for(int i = 0;i < vb.size() ; i ++ ) {
        bcc[vb[i]] = lca;   // Compressing in same BCC
        if(vb[i]==lca) break;
        bridge --;
    }

}

// This reverses the edge of a to root of the connected component
void MakeRoot(int a)
{
    int root = a,child = -1;
    while(a!=-1) {
        int p = getBCC(link[a]);
        link[a] = child;
        comp[a] = root;
        child = a;
        a = p;
    }
    SZ[root] = SZ[child];
}


void addEdge(int a,int b)
{
    a = getBCC(a), b= getBCC(b);
    if(a==b) return;   // Case 1

    int u = getCOMP(a), v = getCOMP(b);
    if(u!=v) {      // Case 2
        bridge ++;
        if(SZ[u] > SZ[v]) {
            swap(a,b);
            swap(u,v);
        }
        MakeRoot(a);
        link[a] = comp[a] = b;
        SZ[v] += SZ[a];
    }
    else MergePath(a,b);    // Case 3
}
int main()
{

    int t;
    cin >> t;
    while(t--) {
        cin >> n >> m;
        init();
        for(int i= 0;i < m; i ++ ) {
            int a,b;
            scanf("%d %d",&a,&b);
            addEdge(a,b);
            printf("%d\n",bridge);
        }
    }
    return 0;
}

Union By Rank

Union By Rank is common Technique in Disjoint-Set.
The application of this technique is needed for Kruskal’s Minimum Spanning Tree.
Normal Kruskal Code using path-compression would look like this .

void init(int n)
{
      for(int i = 1;i <= n;i ++) p[i] = i;
}
int find(int u)
{
	if(p[u]==u) return u;
	else return p[u] = find(p[u]);
}
void Merge(int a,int b)
{
	int u = find(a);
	int v = find(b);
	if(u!=v) {
		p[u] = v ; // p[v] = u both are correct
	}
}

Union By Rank is Simillar to this But We use rank to determine of the new parent.
Rank can be the size of the set.
So the modified code would be

void init(int n)
{
     for(int i= 1;i <= n; i ++ ) p[i] = i,R[i] = 1;
}
int find(int u)
{
	if(p[u]==u) return u;
	else return p[u] = find(p[u]);
}
void Merge(int a,int b)
{
	int u = find(a);
	int v = find(b);
	if(u!=v) {
		if(R[u] > R[v]) {
			P[v] = u;
			R[u] += R[v];
		}
		else {
			P[u] = v;
			R[v] += R[u];
		}
	}
}

Now this technique can be used to particular different kind of problems :

Problem : Link
Discussion From Codeforces Tutorial:

The name of this problem is anagram for ”Small to large”. There is a reason for that 🙂 The author solution for this problem uses the classic technique for computing sets in tree. The simple solution is the following: let’s find for each vertex v the ”map” — the number of occurences for each colour, ”set<pair>” — pairs the number of occurences and the colour, and the number sum — the sum of most frequent colours in subtree of v. To find that firstly we should find the same thing for all childs of v and then merge them to one. These solution is correct but too slow (it works in O(n^2 * logn) time). Let’s improve that solution: every time when we want to merge two map-s a and b let’s merge the smaller one to larger simply by iterating over all elements of the smaller one (this is the “Small to large”). Let’s consider some vertex v: every time when vertex v will be moved from one map to another the size of the new map will be at least two times larger. So each vertex can be moved not over than logn times. Each moving can be done in O(logn) time. If we accumulate that values by all vertices then we get the complexity O(n(logn)^2).

I saw the solutions that differs from author’s but this technique can be used in a lot of other problems.

My code :


/*

 *************************
 Id  : Matrix.code
 Task: 600E
 Date: 2016-01-27

 **************************

 */

#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define Long                    long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define forn(i,n)               for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define SZ(a)                   (int) a.size()
#define all(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define INF                     1<<29
#define EPS                     1e-9
#define Fr                      first
#define Sc                      second
#define Sz                      size()
#define lc                      ((n)<<1)
#define rc                      ((n)<<1|1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define Di(n)                   int n;si(n)
#define Dii(a,b)                int a,b;si(a);si(b)
#define Diii(a,b,c)             int a,b,c;si(a);si(b);si(c)
#define Si(n)                   si(n)
#define Sii(a,b)                si(a);si(b)
#define Siii(a,b,c)             si(a);si(b);si(c)
#define min(a,b)                ((a)>(b) ? (b) : (a) )
#define max(a,b)                ((a)>(b) ? (a):(b))
/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
typedef vector<Long> vl;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void si(T &x){register int c = gc();x = 0;int neg = 0;for(;((c<48 | c>57) && c != '-');c = gc());
      if(c=='-') {neg=1;c=gc();}for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}if(neg) x=-x;}
Long bigmod(Long p,Long e,Long M){Long ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return ret;}
Long gcd(Long a,Long b){if(b==0)return a;return gcd(b,a%b);}
Long modinverse(Long a,Long M){return bigmod(a,M-2,M);}
void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}

/*************************** END OF TEMPLATE ****************************/

const int N = 1e5+5;
map<int,int > T[N];
int p[N];
int c[N];
Long finalAns[N];
vector<int> G[N];
Long iMax[N], cnt[N];

void Merge(int a,int b)
{
      if(SZ(T[p[a]]) < SZ(T[p[b]])) swap(p[a],p[b]);
      int id = p[a];
      for(auto i : T[p[b]]) {
            int col = i.Fr, occ = i.Sc;
            T[id][col] += occ;
            if(T[id][col] > iMax[id] ) {
                  iMax[id] = T[id][col];
                  cnt[id] = col;
            } else if(T[id][col] == iMax[id]) cnt[id] += col;
      }
}
void dfs(int u,int par=-1)
{
      for(auto a: G[u]) if(a!=par) {
            dfs(a,u);
            Merge(u,a);

      }
      finalAns [u] = cnt[p[u]];
}
int main()
{
      //freopen("in.txt","r",stdin);

      Di(n);
      for(int i= 1;i <= n;i ++ ) {
            Si(c[i]);
            p[i] = i;
            cnt[i] = c[i];
            iMax[i] = 1;
            T[i][c[i]] = 1;
      }

      for(int i= 0;i < n-1;i ++ ) {
            Dii(a,b);
            G[a].pb(b);
            G[b].pb(a);
      }
      dfs(1);
      for(int i= 1;i <= n; i++ ) printf("%lld ",finalAns[i]);
      return 0;
}

SPOJ – CERC07B – Strange Billboard

Category: BitMask, Brute force
Link: Link

Discussion: For each possible configuration of the first row, We can determine the next row, then the following. Thus building the structure

//
//  main.cpp
//  CERC07B - Strange Billboard
//
//  Created by Repon Macbook on 12/11/15.
//  Copyright © 2015 Repon Macbook. All rights reserved.
//
/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define Long                    long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define forn(i,n)               for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define all(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define INF                     1<<29
#define EPS                     1e-9
#define Fr                      first
#define Sc                      second
#define Sz                      size()
#define lc                      ((n)<<1)
#define rc                      ((n)<<1|1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define Di(n)                   int n;si(n)
#define Dii(a,b)                int a,b;si(a);si(b)
#define Diii(a,b,c)             int a,b,c;si(a);si(b);si(c)
#define Si(n)                   si(n)
#define Sii(a,b)                si(a);si(b)
#define Siii(a,b,c)             si(a);si(b);si(c)
#define min(a,b)                ((a)>(b) ? (b) : (a) )
#define max(a,b)                ((a)>(b) ? (a):(b))
/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
typedef vector<Long> vl;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void si(T &x){register int c = gc();x = 0;int neg = 0;for(;((c<48 | c>57) && c != '-');c = gc());
      if(c=='-') {neg=1;c=gc();}for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}if(neg) x=-x;}
Long bigmod(Long p,Long e,Long M){Long ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return ret;}
Long gcd(Long a,Long b){if(b==0)return a;return gcd(b,a%b);}
Long modinverse(Long a,Long M){return bigmod(a,M-2,M);}
void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}

/*************************** END OF TEMPLATE ****************************/

const int N = 17;
char x[N][N];
int ar[N];
int temp[N];


int main()
{
      int n,m;
      
      while(scanf("%d%d",&n,&m)==2 ){
            if(n+m==0) return 0;
            forn(i,n) scanf("%s",x[i]);
            forn(i,n){
                  int o = 0;
                  forn(j,m) if(x[i][j]=='X') o |= (1<<j);
                  ar[i] = o;
            }
            int iM = 1e8;
            bool flag = 0;
            forn(i,1<< m ) {
                  forn(k,n) temp[k]= ar[k];
                  int cnt = 0;
                  forn(j,m) {
                        if(i & (1<<j)){
                              temp[0] ^= (1<<j);
                              if(j+1<m) temp[0] ^= (1<<(j+1));
                              if(j-1>=0) temp[0] ^= (1<<(j-1));
                              temp[1] ^= (1<<j);
                              cnt ++;
                        }
                  }
                  for(int i = 1; i< n; i ++ ){
                        for(int j = 0; j< m ;j ++ ) {
                              if(temp[i-1] & 1<<j ) {
                                    temp[i] ^= (1<<j);
                                    if(j+1<m) temp[i] ^= (1<<(j+1));
                                    if(j-1>=0) temp[i] ^= (1<<(j-1));
                                    temp[i+1] ^= (1<<j);
                                    cnt ++;
                              }
                        }
                  }
                  if(temp[n-1] == 0 ) {
                        iM = min(iM, cnt );
                        flag = 1;
                  }
            }
            if(flag) printf("You have to tap %d tiles.\n",iM);
            else printf("Damaged billboard.\n");
            
      }
      
      return 0;
}

Mincost Maxflow Implementation

Problem : Uva – 1317
Discussion:
Algorithm to solve:
Mincost Maxflow
Graph Construct:

1. for i,j,w , give i -> j+1, with capacity 1, cost -w
2. for i=0 to 355, give i->i+1, with capacity 2, cost 0
3. Calculate mincost Max flow, ans = – MincostMaxflow

/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define Long                    long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define forn(i,n)               for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define aT(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define INF                     1<<29
#define EPS                     1e-9
#define Fr                      first
#define Sc                      second
#define Sz                      size()
#define lc                      ((n)<<1)
#define rc                      ((n)<<1|1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define Di(n)                   int n;si(n)
#define Dii(a,b)                int a,b;si(a);si(b)
#define Diii(a,b,c)             int a,b,c;si(a);si(b);si(c)
#define Si(n)                   si(n)
#define Sii(a,b)                si(a);si(b)
#define Siii(a,b,c)             si(a);si(b);si(c)
#define min(a,b)                ((a)>(b) ? (b) : (a) )
#define max(a,b)                ((a)>(b) ? (a):(b))
/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
typedef vector<Long> vl;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void si(T &x){register int c = gc();x = 0;int neg = 0;for(;((c<48 | c>57) && c != '-');c = gc());
      if(c=='-') {neg=1;c=gc();}for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}if(neg) x=-x;}
template <class T> inline T bigmod(T p,T e,T M){Long ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return (T)ret;}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}
void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}

/*************************** END OF TEMPLATE ****************************/
const int N = 370;
typedef long long T;

struct Edge {
      int  u , v ;
      T cap ,flow , cost;
};

struct MCMF {
      int n,m,s,t;      // Total Number of Node Including S,T
      vector<int> G[N];     //Graph
      vector<Edge> E;         // EdgeList
      T d[N];             // Distance Array of BeTmanFord
      bool inq[N];           // Is node in queue
      int p[N];
      int a[N];
      
      void init(T n){
            this->n =n;
            for(T i = 0; i < n ; i ++ ) G[i].clear();
            E.clear();
      }
      
      void addEdge( int u , int v , T cap , T cost ){
            E.push_back({u, v , cap , 0 , cost});       // Positive Cost
            E.push_back({v,u , 0, 0 , -cost } );        // Negative Cost
            m = E.size();
            G[u].push_back(m - 2);
            G[v].push_back(m - 1);
            
      }
      
      bool BelmanFord(T &flow , T &cost ) {
            
            for(int i = 0; i < n ;i  ++) d[i] = INF ;
            memset(inq, 0, sizeof(inq));
            d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF ;
            
            queue<int> Q;
            Q.push(s);
            while(!Q.empty() ) {
                  T u = Q.front(); Q.pop();
                  inq[u] = 0;

                  for( int i = 0 ; i < G[u].size() ; i ++ ) {
                        Edge &e = E[G[u][i]];
                        if( e.cap > e.flow && d[e.v] > d[u] + e.cost ) {
                              d[e.v] = d[u] + e.cost;
                              p[e.v] = G[u][i];
                              a[e.v] = min( a[u] , e.cap - e.flow );
                              
                              if( inq[e.v ] == 0 ) {
                                    Q.push(e.v);
                                    inq[e.v] = 1;
                              }
                        }
                  }
            }
            
            if( d[t] == INF ) return false;     // No augmenting Path
            flow = a[t];
            cost = d[t] ;               // Unit cost
            int u = t ;
            while( u  != s ) {
                  E[p[u]].flow += a[t];
                  E[p[u]^1].flow -= a[t];
                  u = E[p[u]].u;
                  
            }
            
            return true;
      }
      
      T Mincost(  int s, int  t ){
            this->s=s,this->t=t;
            T Mcost = 0;
            T Flow = 0;
            T f = 0 ;    // For Each CaT , The flow
            T d = 0;      // Shortest Distance / Cost Per Flow
            
            while( BelmanFord( f, d) ) {
                  Flow += f;
                  Mcost += f *d ;
            }
            
            return Mcost;
            
      }
} maxf;

int main()
{
      int n;
      while(scanf("%d",&n)==1 && n ) {
            maxf.init(370);
            forn(i,n) {
                  Diii(a,b,c);
                  maxf.addEdge(a,b+1,1,-c);
            }
            forn(i,366) {
                  maxf.addEdge(i,i+1,2,0);
            }
            int Source = 0, Sink = 366;
            T o = maxf.Mincost(Source,Sink);
            printf("%lld\n",-o);
      }
      return 0;
}


All Pair Maximum Flow

Problem : UVA – 11594
Solution : Gomory–Hu tree

Property :
1.The vertex set of the tree and the graph is the same.
2.The maximum flow between vertices u and v in the tree is equal to the maximum flow in the graph.

Using n maxflows, we can create Gomory–Hu tree
Total Complexity : O(n * T(maxflow))
Code :

/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define Long                    long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define forn(i,n)               for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define all(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define INF                     1<<29
#define EPS                     1e-9
#define Fr                      first
#define Sc                      second
#define Sz                      size()
#define lc                      ((n)<<1)
#define rc                      ((n)<<1|1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define Di(n)                   int n;si(n)
#define Dii(a,b)                int a,b;si(a);si(b)
#define Diii(a,b,c)             int a,b,c;si(a);si(b);si(c)
#define Si(n)                   si(n)
#define Sii(a,b)                si(a);si(b)
#define Siii(a,b,c)             si(a);si(b);si(c)
#define min(a,b)                ((a)>(b) ? (b) : (a) )
#define max(a,b)                ((a)>(b) ? (a):(b))
/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
typedef vector<Long> vl;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void si(T &x){register int c = gc();x = 0;int neg = 0;for(;((c<48 | c>57) && c != '-');c = gc());
      if(c=='-') {neg=1;c=gc();}for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}if(neg) x=-x;}
template <class T> inline T bigmod(T p,T e,T M){Long ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return (T)ret;}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}
void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}

/*************************** END OF TEMPLATE ****************************/
const int N = 205;

struct Edge{
      int u,v;
      Long cap,flow;
};
struct Dinic{
      int n,m,s,t;
      vector<int>G[N];
      vector<Edge>E;
      int cur[N];
      int d[N];
      bool vis[N];
      
      void init(int n)
      {
            this->n=n;
            forn(i,n+1) G[i].clear();
            E.clear();
      }
      
      void addEdge(int u,int v,Long cap)
      {
            E.push_back({u,v,cap,0});
            E.push_back({v,u,0,0});
            m = E.Sz;
            G[u].pb(m-2);
            G[v].pb(m-1);
      }
      
      bool bfs()
      {
            ms(vis,0);
            queue<int>q;
            q.push(s);
            vis[s]=1;
            d[s] = 0;
            while(!q.empty()){
                  int u = q.front() ; q.pop();
                  for(int i = 0; i < G[u].Sz;i ++ ) {
                        Edge &e = E[G[u][i]];
                        if(vis[e.v] == 0 && e.cap > e.flow) {
                              vis[e.v]  =1;
                              d[e.v] = 1 + d[u];
                              q.push(e.v);
                        }
                  }
            }
            return vis[t];
      }
      
      Long dfs(int u,Long oo)
      {
            if(u==t || oo == 0) return oo;
            Long Flow = 0, f;
            for(int &i = cur[u] ; i < G[u].Sz ; i ++ ) {
                  Edge &e= E[G[u][i]];
                  if(d[e.v] == 1 + d[u] && (f = dfs(e.v , min(oo  , e.cap - e.flow))) > 0 ){
                        e.flow += f;
                        E[G[u][i] ^1 ].flow -=f;
                        Flow += f;
                        oo-=f;
                        if(oo == 0 ) break;
                  }
            }
            return Flow;
            
      }
      
      Long dinitz(int s,int t)
      {
            this->s= s, this->t=t;
            Long Mf = 0;
            while(bfs()){
                  ms(cur,0);
                  Mf += dfs(s,1LL<<45);
            }
            return Mf;
      }
      vector<int> getCut()
      {
            vector<int>cut;
            for(int i = 0;i < E.Sz; i ++ ) {
                  Edge &e = E[i];
                  if(e.flow > 0 && e.cap == e.flow ) cut.pb(i);
            }
            return cut;
      }
      
      void clear()
      {
            for(int i = 0;i < m ;i ++ ) E[i].flow = 0;
      }
      
      
}MaxF;

int F[N];
Long Ans[N][N];
int e[N];
vector<ii> T[N];
int id;

void dfs(int u,int p ,Long flow )
{
      
      for(auto a: T[u]) if(a.Fr != p) {
            Ans[id][a.Fr] = min(flow, a.Sc);
            dfs(a.Fr, u, min(flow  , a.Sc ));
      }
}
int main()
{
      Di(t);
      int cs = 0;
      while(t--) {
            Di(n);
            MaxF.init(n);
            forn(i,n ) forn(j,n) {
                  Di(a);
                  if(a)MaxF.addEdge(i,j,a);
            }
            /**************** Construction of Gomory- tree ****************/
            forn(i,n) F[i] = 0; 
            for(int i=1;i<n;i++ ){
                  MaxF.clear();
                  e[i] = MaxF.dinitz(i,F[i]); // MaxFlow 
                  MaxF.bfs();
                  for(int j = i+1; j< n; j ++ ) {
                        if(MaxF.vis[j] && F[j] == F[i] ) F[j]= i; // S-T Cut
                  }
            }
            // New Graph Creation
            for(int i = 1; i< n; i ++ ) {
                  T[i].pb(mp(F[i],e[i]));
                  T[F[i]].pb(mp(i,e[i]));
            }
            /* *************** END ******************************************/
            forn(i,n) {
                  id = i;
                  dfs(i,-1, 1LL<<60 );
            }
            printf("Case #%d:\n",++cs);
            forn(i,n) {
                  forn(j,n){
                        if(j) printf(" ");
                        printf("%lld", Ans[i][j]);
                  }
                  printf("\n");
            }
            forn(i,n) T[i].clear();
            
      }
      return 0;
}


CF – 510E – Fox And Dinner

Category : MaxFlow
Discussion:
First finding is: if a + b is a prime, then one of them is an odd number, another is an even number. (that’s why we set 2 ≤ xi)

Then we could find: every odd number have exactly 2 even number as neighborhood, and every even number have exactly 2 odd number as neighborhood. And that means we need |#even| = |#odd| to have a solution.

So it looks like bipartite graph matching, but every element matched 2 elements. And in fact it can be handled by maxflow: For each odd number, we add a node on the left side and link it from source with capacity equals to 2, and for each even number, we add a node on the right side and link it to sink with capacity equals to 2. And if sum of two numbers is a prime number, we link them with capacity equals to 1.

Then we solve the max flow, it have solution if and only if maxflow = 2 * |#even|.

We can construct the answer(cycles) from the matches.

/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define Long                    long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define forn(i,n)               for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define all(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define INF                     1<<29
#define EPS                     1e-9
#define Fr                      first
#define Sc                      second
#define Sz                      size()
#define lc                      ((n)<<1)
#define rc                      ((n)<<1|1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define Di(n)                   int n;si(n)
#define Dii(a,b)                int a,b;si(a);si(b)
#define Diii(a,b,c)             int a,b,c;si(a);si(b);si(c)
#define Si(n)                   si(n)
#define Sii(a,b)                si(a);si(b)
#define Siii(a,b,c)             si(a);si(b);si(c)
#define min(a,b)                ((a)>(b) ? (b) : (a) )
#define max(a,b)                ((a)>(b) ? (a):(b))
/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
typedef vector<Long> vl;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void si(T &x){register int c = gc();x = 0;int neg = 0;for(;((c<48 | c>57) && c != '-');c = gc());
      if(c=='-') {neg=1;c=gc();}for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}if(neg) x=-x;}
Long bigmod(Long p,Long e,Long M){Long ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return ret;}
Long gcd(Long a,Long b){if(b==0)return a;return gcd(b,a%b);}
Long modinverse(Long a,Long M){return bigmod(a,M-2,M);}
void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}

/*************************** END OF TEMPLATE ****************************/
const int N = 405;



typedef Long T;

struct Edge{
      int u,v;
      T cap,flow;
      
};
struct Dinic{
      int n,m,s,t;
      vector<Edge>E;
      vi G[N];
      bool vis[N];
      int d[N];
      int cur[N];
      
      
      void init(int n)
      {
            this->n=n;
            forn(i,n+1) G[i].clear();
            E.clear();
      }
      void addEdge(int u,int v, T cap)
      {
            E.push_back({u,v,cap,0});
            E.push_back({v,u,0,0});
            m = E.Sz;
            G[u].pb(m-2);
            G[v].pb(m-1);
      }
      
      bool bfs()
      {
            ms(vis,0);
            d[s]=0;
            queue<int>q;
            q.push(s);
            vis[s] = 1;
            while(!q.empty()){
                  int u = q.front(); q.pop();
                  for(int i = 0;i < G[u].Sz; i ++ ) {
                        Edge &e = E[G[u][i]];
                        if(vis[e.v] == 0 && e.cap > e.flow ) {
                              vis[e.v] = 1;
                              d[e.v] = 1 + d[u];
                              q.push(e.v);
                        }
                  }
            }
            return vis[t];
      }
      
      T dfs(int u, T oo){
            if(oo == 0  || u == t) return oo;
            T Fl = 0, f;
            for(int &i = cur[u] ; i < G[u].Sz; i ++ ) {
                  Edge &e = E[G[u][i]];
                  if(d[e.v] == 1 + d[u] && (f = dfs(e.v, min(oo, e.cap - e.flow))) > 0 ) {
                        e.flow += f;
                        E[G[u][i] ^1 ].flow -= f;
                        Fl +=f ;
                        oo -= f;
                        if(oo == 0 ) break;
                  }
            }
            return Fl;
      }
      
      T dinitz(int s,int t)
      {
            this->s =  s , this->t=t;
            T Flow = 0;
            while(bfs()){
                  ms(cur,0);
                  T oo = dfs(s,INF);
                  
                  Flow += oo;
                  
            }
            return Flow;
      }
      
      
}MaxF;
const int MX = 2e4+5;
bool vis[MX];
vi Prime;
void seive()
{
      vis[0]=vis[1] = 1;
      for(int i=2 ; i < MX; i ++ ) {
            if(vis[i] == 0 ) {
                  Prime.pb(i);
                  for(int j= 2; i *j < MX ; j ++ ) {
                        vis[i*j] = 1;
                  }
            }
      }
      //forn(i,100) if(vis[i] == 0 ) printf("%d\n" , i);
}

struct info{
      int a,id;
      int node;
      info(){}
      info(int a,int id,int node):a(a),id(id),node(node){}
      
      
};
vector<info> odd,even;

vi nodes;

int Map[N];

void dfs(int u,int p)
{
      if(vis[u] ) return;
      vis[u] = 1;
      nodes.pb(Map[u]);
      for(int i = 0; i < MaxF.G[u].Sz ; i ++ ) {
            Edge e = MaxF.E[MaxF.G[u][i]];
            if((e.flow ==1 || e.flow == -1) && e.v != p) {
                  dfs(e.v,u);
                  return;
            }
      }
      
}


int main()
{
      seive();
      Di(n);
      int cnt = 1;
      for(int i = 1;i <= n;i ++ ) {
            Di(a);
            if(a%2) odd.pb(info(a,i,cnt++));
            else even.pb(info(a,i,cnt++));
            Map[cnt-1] = i;
      }
      if(odd.Sz != even.Sz) printf("Impossible\n");
      else {
            MaxF.init(n+2);
            int k = n / 2;
            int Source = 0, Sink= cnt+1;
            for(auto a: odd)  {
                  MaxF.addEdge(Source, a.node,2);
            }
            for(auto a: even ) {
                  MaxF.addEdge(a.node,Sink,2);
            }
            for(auto a: odd) {
                  for(auto b : even ) {
                        if(vis[a.a+b.a] == 0 ) {
                              MaxF.addEdge(a.node,b.node,1);
                        }
                  }
            }
            T o = MaxF.dinitz(Source, Sink);
            if( o == n ) {
                  int cnt = 0;
                  ms(vis,0);
                  vector<int> L[100];
                  for(auto a: odd) {
                        if(vis[a.node] == 0 ) {
                              dfs(a.node,-1);
                              L[cnt++] = nodes;
                              nodes.clear();
                        }
                        
                  }
                  
                  printf("%d\n", cnt);
                  forn(i,cnt){
                        printf("%ld", L[i].Sz);
                        for(auto p: L[i]) printf(" %d",p);
                        printf("\n");
                  }
            }
            else printf("Impossible\n");
      }
      return 0;
}

CF – 546E – Soldier and Traveling

Category : MaxFlow
Discussion From editorial:
Let’s build a flow network in following way:

Make a source.

Make a first group of vertices consisting of n vertices, each of them for one city.

Connect a source with ith vertex in first group with edge that has capacity ai.

Make a sink and second group of vertices in the same way, but use bi except for ai.

If there is a road between cities i and j or i = j. Make two edges, first should be connecting ith vertex from first group, and jth vertex from second group, and has infinity capacity. Second should be similar, but connect jth from first group and ith from second group.

Then find a maxflow, in any complexity.

If maxflow is equal to sum of ai and is equal to sum of bi, then there exists an answer. How can we get it? We just have to check how many units are we pushing through edge connecting two vertices from different groups.


/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define Long                    long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define forn(i,n)               for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define all(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define INF                     1<<29
#define EPS                     1e-9
#define Fr                      first
#define Sc                      second
#define Sz                      size()
#define lc                      ((n)<<1)
#define rc                      ((n)<<1|1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define Di(n)                   int n;si(n)
#define Dii(a,b)                int a,b;si(a);si(b)
#define Diii(a,b,c)             int a,b,c;si(a);si(b);si(c)
#define Si(n)                   si(n)
#define Sii(a,b)                si(a);si(b)
#define Siii(a,b,c)             si(a);si(b);si(c)
#define min(a,b)                ((a)>(b) ? (b) : (a) )
#define max(a,b)                ((a)>(b) ? (a):(b))
/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
typedef vector<Long> vl;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void si(T &x){register int c = gc();x = 0;int neg = 0;for(;((c<48 | c>57) && c != '-');c = gc());
      if(c=='-') {neg=1;c=gc();}for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}if(neg) x=-x;}
Long bigmod(Long p,Long e,Long M){Long ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return ret;}
Long gcd(Long a,Long b){if(b==0)return a;return gcd(b,a%b);}
Long modinverse(Long a,Long M){return bigmod(a,M-2,M);}
void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}

/*************************** END OF TEMPLATE ****************************/
const int N = 205;
typedef Long T;

struct Edge{
      int u,v;
      T cap,flow;
      
};
struct Dinic{
      int n,m,s,t;
      vector<Edge>E;
      vi G[N];
      bool vis[N];
      int d[N];
      int cur[N];
      
      
      void init(int n)
      {
            this->n=n;
            forn(i,n+1) G[i].clear();
            E.clear();
      }
      void addEdge(int u,int v, T cap)
      {
            E.push_back({u,v,cap,0});
            E.push_back({v,u,0,0});
            m = E.Sz;
            G[u].pb(m-2);
            G[v].pb(m-1);
      }
      
      bool bfs()
      {
            ms(vis,0);
            d[s]=0;
            queue<int>q;
            q.push(s);
            vis[s] = 1;
            while(!q.empty()){
                  int u = q.front(); q.pop();
                  for(int i = 0;i < G[u].Sz; i ++ ) {
                        Edge &e = E[G[u][i]];
                        if(vis[e.v] == 0 && e.cap > e.flow ) {
                              vis[e.v] = 1;
                              d[e.v] = 1 + d[u];
                              q.push(e.v);
                        }
                  }
            }
            return vis[t];
      }
      
      T dfs(int u, T oo){
            if(oo == 0  || u == t) return oo;
            T Fl = 0, f;
            for(int &i = cur[u] ; i < G[u].Sz; i ++ ) {
                  Edge &e = E[G[u][i]];
                  if(d[e.v] == 1 + d[u] && (f = dfs(e.v, min(oo, e.cap - e.flow))) > 0 ) {
                        e.flow += f;
                        E[G[u][i] ^1 ].flow -= f;
                        Fl +=f ;
                        oo -= f;
                        if(oo == 0 ) break;
                  }
            }
            return Fl;
      }
      
      T dinitz(int s,int t)
      {
            this->s =  s , this->t=t;
            T Flow = 0;
            while(bfs()){
                  ms(cur,0);
                  T oo = dfs(s,INF);
                 
                  Flow += oo;
                  
            }
            return Flow;
      }
      
      
}MaxF;


int a[N] , b[N];

int Ans[N][N];

int main()
{
      
      Dii(n,m);
      int Sum = 0;
      for(int i = 1;i <= n; i ++ ) {
            Si(a[i]); Sum += a[i];
      }
      int SS = 0;
      for(int i = 1;i <= n; i ++ )  Si(b[i]), SS += b[i];
      if(SS != Sum ) {
            printf("NO\n");
            return 0;
      }
      MaxF.init(2*n+2);
      while(m--) {
            Dii(a,b);
            MaxF.addEdge(a,b+n,INF);
            MaxF.addEdge(b,a+n,INF);
            
      }
      int Source = 0, Sink = 2*n+1;
      for(int i= 1; i<= n;i ++) {
            MaxF.addEdge(Source,i,a[i]);
      }
      for(int i = 1;i <=n ;i ++ ) {
            MaxF.addEdge(i+n, Sink , b[i]);
      }
      for(int i = 1; i<= n;i ++ ) {
            MaxF.addEdge(i,i+n,INF);
      }
      T o = MaxF.dinitz(Source, Sink);
      if(o== Sum ) {
            printf("YES\n");
            
            for(int i = 1; i<= n;i ++ ) {
                  for(int j = 0; j < MaxF.G[i].Sz; j ++ ) {
                        Edge e = MaxF.E[MaxF.G[i][j]];
                        if(e.flow > 0 )Ans[i][e.v- n] = e.flow;
                        
                  }
            }
            for(int i= 1; i <= n; i ++ ) {
                  for(int j = 1;j <= n; j ++ ) printf("%d ", Ans[i][j]);
                  printf("\n");
            }
      }else printf("NO\n");
      return 0;
}

UVA – 11248 – Frequency Hopping

Category : Maxflow
Implementation : Dinic
Discussion:
1. First determine MF, if MF >= C , “possible”
2. If not , Determine Cut edges, Increase the capacity of cut edges , Determine MF, if MF >= C , possible optio
3. In case 2, no MF >=C , answer = no

/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define Long                    long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define forn(i,n)               for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define all(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define INF                     1<<29
#define EPS                     1e-9
#define Fr                      first
#define Sc                      second
#define Sz                      size()
#define lc                      ((n)<<1)
#define rc                      ((n)<<1|1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define Di(n)                   int n;si(n)
#define Dii(a,b)                int a,b;si(a);si(b)
#define Diii(a,b,c)             int a,b,c;si(a);si(b);si(c)
#define Si(n)                   si(n)
#define Sii(a,b)                si(a);si(b)
#define Siii(a,b,c)             si(a);si(b);si(c)
#define min(a,b)                ((a)>(b) ? (b) : (a) )
#define max(a,b)                ((a)>(b) ? (a):(b))
/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
typedef vector<Long> vl;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void si(T &x){register int c = gc();x = 0;int neg = 0;for(;((c<48 | c>57) && c != '-');c = gc());
      if(c=='-') {neg=1;c=gc();}for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}if(neg) x=-x;}
template <class T> inline T bigmod(T p,T e,T M){Long ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return (T)ret;}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}
void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}

/*************************** END OF TEMPLATE ****************************/
const int N = 105;
int n,e;
Long Need;
struct Edge{
      int u,v;
      Long cap,flow;
};
struct Dinic{
      int n,m,s,t;
      vector<int>G[N];
      vector<Edge>E;
      int cur[N];
      int d[N];
      bool vis[N];
      
      void init(int n)
      {
            this->n=n;
            forn(i,n+1) G[i].clear();
            E.clear();
      }
      
      void addEdge(int u,int v,Long cap)
      {
            E.push_back({u,v,cap,0});
            E.push_back({v,u,0,0});
            m = E.Sz;
            G[u].pb(m-2);
            G[v].pb(m-1);
      }
      
      bool bfs()
      {
            ms(vis,0);
            queue<int>q;
            q.push(s);
            vis[s]=1;
            d[s] = 0;
            while(!q.empty()){
                  int u = q.front() ; q.pop();
                  for(int i = 0; i < G[u].Sz;i ++ ) {
                        Edge &e = E[G[u][i]];
                        if(vis[e.v] == 0 && e.cap > e.flow) {
                              vis[e.v]  =1;
                              d[e.v] = 1 + d[u];
                              q.push(e.v);
                        }
                  }
            }
            return vis[t];
      }
      
      Long dfs(int u,Long oo)
      {
            if(u==t || oo == 0) return oo;
            Long Flow = 0, f;
            for(int &i = cur[u] ; i < G[u].Sz ; i ++ ) {
                  Edge &e= E[G[u][i]];
                  if(d[e.v] == 1 + d[u] && (f = dfs(e.v , min(oo  , e.cap - e.flow))) > 0 ){
                        e.flow += f;
                        E[G[u][i] ^1 ].flow -=f;
                        Flow += f;
                        oo-=f;
                        if(oo == 0 ) break;
                  }
            }
            return Flow;
            
      }
      
      Long dinitz(int s,int t)
      {
            this->s= s, this->t=t;
            Long Mf = 0;
            while(bfs()){
                  ms(cur,0);
                  Mf += dfs(s,1LL<<45);
                  if(Mf >= Need ) return Mf;
            }
            return Mf;
      }
      vector<int> getCut()
      {
            vector<int>cut;
            for(int i = 0;i < E.Sz; i ++ ) {
                  Edge &e = E[i];
                  if(e.flow > 0 && e.cap == e.flow ) cut.pb(i);
            }
            return cut;
      }
      
      
}MaxF;

int main()
{
      int cs = 0;
      while(scanf("%d %d %lld",&n,&e,&Need) == 3) {
            if(n==0&&e==0 && Need==0) break;
            MaxF.init(n);
            forn(i,e) {
                  Diii(a,b,c);
                  MaxF.addEdge(a,b,c);
            }
            Long nf = MaxF.dinitz(1,n);
            if(nf >= Need ) printf("Case %d: possible\n",++cs);
            else {
                  vi cut=  MaxF.getCut();
                  vector<ii> Ans;
                  for(int i = 0; i< cut.Sz; i ++ ) {
                        forn(i, MaxF.E.Sz) MaxF. E[i].flow = 0;
                        Long prv = MaxF.E[cut[i]].cap;
                        MaxF.E[cut[i]].cap = Need;
                        nf = MaxF.dinitz(1,n);
                        if(nf >= Need) {
                              Ans.pb(mp(MaxF. E[cut[i]].u ,MaxF. E[cut[i]].v));
                        }
                        forn(i,MaxF.E.Sz) MaxF.E[i].flow = 0;
                        MaxF.E[cut[i]].cap= prv;
                        
                  }
                  if(Ans.Sz) {
                        sort(all(Ans));
                        printf("Case %d: possible option:",++cs);
                        forn(i,Ans.Sz) {
                              if(i) printf(",");
                              printf("(%d,%d)",Ans[i].Fr, Ans[i].Sc);
                        }
                        printf("\n");
                  }else printf("Case %d: not possible\n",++cs);
            }
      }
      
}

MaxFlow Dinic Algorithm Implementation

Problem : UVA 820
Category : Maxflow in undirected graph

/*
 
 *************************
 Id  : Matrix.code
 Task:
 Date:
 
 **************************
 
 */

#include <bits/stdc++.h>
using namespace std;

/*------- Constants---- */

#define Long                    long long
#define ull                     unsigned long long
#define mod                     1000000007
#define MEMSET_INF              63
#define MEM_VAL                 1061109567
#define forn(i,n)               for( int i=0 ; i < n ; i++ )
#define mp(i,j)                 make_pair(i,j)
#define lop(i,a,b)              for( int i = (a) ; i < (b) ; i++)
#define pb(a)                   push_back((a))
#define all(x)                  (x).begin(),(x).end()
#define gc                      getchar_unlocked
#define PI                      acos(-1.0)
#define INF                     1<<29
#define EPS                     1e-9
#define Fr                      first
#define Sc                      second
#define Sz                      size()
#define lc                      ((n)<<1)
#define rc                      ((n)<<1|1)
#define db(x)                   cout << #x << " -> " << x << endl;
#define Di(n)                   int n;si(n)
#define Dii(a,b)                int a,b;si(a);si(b)
#define Diii(a,b,c)             int a,b,c;si(a);si(b);si(c)
#define Si(n)                   si(n)
#define Sii(a,b)                si(a);si(b)
#define Siii(a,b,c)             si(a);si(b);si(c)
#define min(a,b)                ((a)>(b) ? (b) : (a) )
#define max(a,b)                ((a)>(b) ? (a):(b))
/*---- short Cuts ------- */
#define ms(ara_name,value) memset(ara_name,value,sizeof(ara_name))
typedef pair<int, int> ii;
typedef vector<int > vi ;
typedef vector<Long> vl;
/*------ template functions ------ */
#ifndef getchar_unlocked
#define getchar_unlocked getchar
#endif
template<class T> inline void si(T &x){register int c = gc();x = 0;int neg = 0;for(;((c<48 | c>57) && c != '-');c = gc());
      if(c=='-') {neg=1;c=gc();}for(;c>47 && c<58;c = gc()) {x = (x<<1) + (x<<3) + c - 48;}if(neg) x=-x;}
template <class T> inline T bigmod(T p,T e,T M){Long ret = 1;for(; e > 0; e >>= 1){if(e & 1) ret = (ret * p) % M;p = (p * p) % M;} return (T)ret;}
template <class T> inline T gcd(T a,T b){if(b==0)return a;return gcd(b,a%b);}
template <class T> inline T modinverse(T a,T M){return bigmod(a,M-2,M);}
void io(){freopen("/Users/MyMac/Desktop/in.txt","r",stdin);}

/*************************** END OF TEMPLATE ****************************/


const int N = 3003;
typedef int T;
struct Edge
{
    int u, v;
    T cap, flow;
    Edge(int u, int v, T c, T f):u(u), v(v), cap(c), flow(f) {}
};

struct Dinic
{
    int n, m, s, t;
    const T oo = 1e9;
    vector<Edge> edge;
    vector<int> G[N];
    bool vis[N];
    int d[N];
    int cur[N];

    void init(int n)
    {
        this->n=n;
        for(int i=0; i<=n; i++)
            G[i].clear();
        edge.clear();
    }

    void addEdge(int u, int v, int cap)
    {
        edge.push_back(Edge(u, v, cap, 0));
        edge.push_back(Edge(v, u, cap, 0));
        m=edge.size();
        G[u].push_back(m-2);
        G[v].push_back(m-1);
    }

    bool bfs()
    {
        memset(vis, 0, sizeof vis);
        queue<int> q;
        q.push(s);
        d[s]=0;
        vis[s]=1;
        while(!q.empty())
        {
            int x=q.front();
            q.pop();
            for(int i=0; i<G[x].size(); i++)
            {
                Edge& e=edge[G[x][i]];
                if(!vis[e.v] && e.cap>e.flow)
                {
                    vis[e.v]=true;
                    d[e.v]=d[x]+1;
                    q.push(e.v);
                }
            }
        }
        return vis[t];
    }

    T dfs(int x, T a)
    {
        if(x==t || a==0)return a;
        T flow=0, f;
        for(int& i=cur[x]; i<G[x].size(); i++)
        {
            Edge& e=edge[G[x][i]];
            if(d[x]+1==d[e.v] && (f=dfs(e.v, min(a, e.cap-e.flow)))>0)
            {
                e.flow+=f;
                edge[G[x][i]^1].flow-=f;
                flow+=f;
                a-=f;
                if(a==0)break;
            }
        }
        return flow;
    }

    T dinitz(int s, int t)
    {
        this->s=s;
        this->t=t;
        int flow=0;
        while(bfs())
        {
            memset(cur, 0, sizeof cur);
            flow+=dfs(s, oo);
        }
        return flow;
    }
} MaxF;

int main() {
      int n;
      int cs = 0;
      while(scanf("%d",&n) && n ) {
            Diii(u,v,m);
            MaxF.init(n);
            forn(i,m) {
                  Diii(a,b,c);
                  MaxF.addEdge(a,b,c);
            
            }
            printf("Network %d\nThe bandwidth is %lld.\n\n",++cs, MaxF.dinitz(u,v));
      }
      
      return 0;
}