Cod sursa(job #1709378)

Utilizator depevladVlad Dumitru-Popescu depevlad Data 28 mai 2016 12:01:23
Problema Tribut Scor 0
Compilator cpp Status done
Runda ONIS 2016 - Runda - 2 - ACM ICPC Romanian Programming Contest Marime 2.96 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <queue>

using namespace std;

const int N_MAX = 505;

int N, M, S, D;
vector<int> graph[N_MAX];
int cap[N_MAX][N_MAX];
int flow[N_MAX][N_MAX];

inline int PlanetIn(int x) {
   return x;
}

inline int PlanetOut(int x) {
   return N + x;
}

inline int Union(int x) {
   return 2 * N + x;
}

inline void AddEdge(int x, int y, int c) {
   graph[x].push_back(y);
   graph[y].push_back(x);
   cap[x][y] = c;
}

int dist[N_MAX];
int father[N_MAX];
bool visited[N_MAX];
queue<int> q;

bool Bfs() {
   fill(dist, dist + N_MAX, numeric_limits<int> :: max());
   fill(father, father + N_MAX, -1);
   fill(visited, visited + N_MAX, 0);
   
   visited[S] = 1;
   father[S] = S;
   dist[S] = 0;
   
   for(q.push(S); !q.empty(); q.pop()) {
      int x = q.front();
      if(x != D) {
         for(vector<int> :: iterator it = graph[x].begin(); it != graph[x].end(); ++it) {
            if(flow[x][*it] < cap[x][*it] && !visited[*it]) {
               visited[*it] = 1;
               dist[*it] = dist[x] + 1;
               father[*it] = x;
               q.push(*it);
            }
         }
      }
   }
   
   return visited[D];
}

int maxFlow;

bool IncreaseFlow() {
   if(!Bfs())
      return 0;
   
   for(vector<int> :: iterator it = graph[D].begin(); it != graph[D].end(); it++) {
      if(visited[*it]) {
         father[D] = *it;
         
         int thisFlow = numeric_limits<int> :: max();
         for(int i = D; i != S; i = father[i])
            thisFlow = min(thisFlow, cap[father[i]][i] - flow[father[i]][i]);
         for(int i = D; i != S; i = father[i])
            flow[father[i]][i] += thisFlow, flow[i][father[i]] -= thisFlow;
         
         maxFlow += thisFlow;
      }
   }
   
   return 1;
}

int v[N_MAX];
int vUnion[N_MAX];

void Reset() {
   fill(v, v + N_MAX, 0);
   fill(vUnion, vUnion + N_MAX, 0);
   
   for(int i = 0; i < N_MAX; i++) {
      for(int j = 0; j < N_MAX; j++) {
         cap[i][j] = 0;
         flow[i][j] = 0;
      }
   }
   
   for(int i = 0; i < N_MAX; i++)
      graph[i].clear();
   
   S = 0;
   D = N_MAX - 1;
   maxFlow = 0;
}

int main() {
   ifstream f("tribut.in");
   ofstream g("tribut.out");
   
   int T;
   
   f >> T;
   while(T--) {
      Reset();
      
      f >> N >> M;
      for(int i = 1; i <= N; i++) {
         f >> v[i];
         AddEdge(PlanetIn(i), PlanetOut(i), v[i]);
      }
      for(int i = 1, cnt; i <= M; i++) {
         f >> cnt >> vUnion[i];
         for(int j = 1, x; j <= cnt; j++) {
            f >> x;
            AddEdge(PlanetOut(x), Union(i), v[j]);
         }
      }
      for(int i = 1; i <= N; i++)
         AddEdge(S, PlanetIn(i), numeric_limits<int> :: max());
      for(int i = 1; i <= M; i++)
         AddEdge(Union(i), D, vUnion[i]);
   
      while(IncreaseFlow());
      
      g << maxFlow << '\n';
   }
   
   return 0;
}