Cod sursa(job #2490552)

Utilizator NicolaalexandraNicola Alexandra Mihaela Nicolaalexandra Data 10 noiembrie 2019 14:54:09
Problema Pixels Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.3 kb
#pragma GCC optimize("Ofast") /// nu stiu cum se foloseste asta dar m am saturat sa iau tle
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include <fstream>
#include <vector>
#include <deque>
#define DIM 2010
#define INF 2000000000
using namespace std;
class InParser {
private:
	FILE *fin;
	char *buff;
	int sp;

	char read_ch() {
		++sp;
		if (sp == 4096) {
			sp = 0;
			fread(buff, 1, 4096, fin);
		}
		return buff[sp];
	}

public:
	InParser(const char* nume) {
		fin = fopen(nume, "r");
		buff = new char[4096]();
		sp = 4095;
	}

	InParser& operator >> (int &n) {
		char c;
		while (!isdigit(c = read_ch()) && c != '-');
		int sgn = 1;
		if (c == '-') {
			n = 0;
			sgn = -1;
		} else {
			n = c - '0';
		}
		while (isdigit(c = read_ch())) {
			n = 10 * n + c - '0';
		}
		n *= sgn;
		return *this;
	}

	InParser& operator >> (long long &n) {
		char c;
		n = 0;
		while (!isdigit(c = read_ch()) && c != '-');
		long long sgn = 1;
		if (c == '-') {
			n = 0;
			sgn = -1;
		} else {
			n = c - '0';
		}
		while (isdigit(c = read_ch())) {
			n = 10 * n + c - '0';
		}
		n *= sgn;
		return *this;
	}
};

vector <int> L[DIM],edges[DIM];
deque <int> c;
int capacitate[DIM][DIM],cap[DIM][DIM],f[DIM][DIM],dist[DIM];
int n,k,i,j,nr1,sursa,dest,nr,x;
void bfs (int sursa, int dest){
    for (int i=sursa;i<=dest;++i){
        edges[i].clear();
        dist[i] = INF;
    }
    c.clear();
    c.push_back(sursa);
    dist[sursa] = 0;
    while (!c.empty()){
        int nod = c.front();
        c.pop_front();
        if (nod == dest)
            break;
        for (int i=0;i<L[nod].size();++i){
            int vecin = L[nod][i];
            if (!capacitate[nod][vecin])
                continue;
            if (dist[vecin] == INF){
                dist[vecin] = 1+dist[nod];
                c.push_back(vecin);
            }
            if (dist[vecin] == 1+dist[nod])
                edges[nod].push_back(vecin);
        }}}
int dfs (int nod, int dest, int max_flow){
    if (nod == dest || !max_flow)
        return max_flow;
    int flow = 0;
    for (int i=0;i<edges[nod].size();++i){
        int vecin = edges[nod][i];
        if (!capacitate[nod][vecin])
            continue;
        int val = dfs (vecin,dest,min(capacitate[nod][vecin],max_flow-flow));
        flow += val;
        capacitate[nod][vecin] -= val;
        capacitate[vecin][nod] += val;
    }
    return flow;
}
int verif (int val){
    /// capacitatile
    for (int i=sursa;i<=dest;++i)
        for (int j=sursa;j<=dest;++j)
            capacitate[i][j] = cap[i][j];

    for (int i=k+2;i<=k+n;i++)
        capacitate[i][dest] = val;
    /// acum bagam flux
    int sol = 0, flux = 0;
    do{
        bfs (sursa,dest);
        flux = dfs (sursa,dest,INF);
        sol += flux;

    } while (flux);

    if (sol == k-nr1)
        return 1;
    return 0;

}
int main (){
    InParser fin ("necromancer.in");
    ofstream fout ("necromancer.out");
    fin>>k>>n;
    /// n candidati si k cetateni
    /// muchie intre sursa si cetateni
    sursa = 0, dest = n+k+1;
    for (i=1;i<=k;++i){
        L[sursa].push_back(i);
        L[i].push_back(sursa);
        cap[sursa][i] = 1;
    }
    for (i=1;i<=k;++i){
        fin>>nr;
        for (j=1;j<=nr;++j){
            fin>>x;
            if (j > 1) /// x nu poate fi pus pe primul loc
                f[i][x] = 1;
        }
        if (!f[i][1]) /// pot sa l fixez pe 1 primul
            nr1++;
        else {
            for (j=2;j<=n;++j){
                L[i].push_back(k+j);
                L[k+j].push_back(i);
                if (!f[i][j])
                    cap[i][k+j] = 1;
            }}}
    if (nr1 > k/2){
        fout<<0;
        return 0;
    }
    for (i=1+k;i<=n+k;++i){
        L[i].push_back(dest);
        L[dest].push_back(i);
    }

    /// incerc sa fixez o limita superioara de voturi pt fiecare candidat => o caut binar
    /// vr sa gasesc cel mai mic nr de voturi pe care il pot avea toti concurentii
    int st = 0, dr = k-nr1, sol = 0;
    while (st <= dr){
        int mid = (st+dr)>>1;
        if (verif(mid)){
            dr = mid-1;
            sol = mid;
        } else st = mid+1;
    }

    fout<<sol-nr1+1;


    return 0;
}