dinic
int bfs() {
queue<int> q;
fill(d, d + maxn, 0);
d[s] = 1;
q.push(s);
while(!q.empty()) {
int x = q.front();
q.pop();
for(int i = G[x].size() - 1 ; i >= 0 ; i -- ){
edge& e = edges[G[x][i]];
if(!d[e.to] && e.val > 0) {
d[e.to] = d[e.from] + 1;
q.push(e.to);
}
}
}
return d[t] > 0;
}
int dfs(int u, long long flow) {
if(u == t)
return flow;
int from = u;
for(int i = G[from].size() - 1 ; i >=0 ; i-- ){
edge& e = edges[G[from][i]];
int v = e.to;
if(d[v] == d[u] + 1 && e.val > 0) {
int res = dfs(v, min(flow, e.val));
if(res > 0) {
e.val -= res;
edges[G[from][i]^1].val += res;
if(u != s && v != t)
nxt[u] = v;
if(u != s && v > n)
tag[v - n] = 1;
return res;
}
}
}
return 0;
}
int dinic() {
int res = 0;
while(bfs()) {
while(int d = dfs(s, inf))
res += d;
}
for(int i = 1; i <= n; i++) {
if(!tag[i]) {
int u = i;
printf("%d ", u);
while(nxt[u] && nxt[u] != t) {
printf("%d ", nxt[u] - n);
u = nxt[u] - n;
}
cout <<"\n";
}
}
return res;
}
ISAP
void bfs(){
fill(d, d + maxn, -1);
fill(gap, gap + maxn, 0);
d[t] = 0;
gap[d[t]] ++ ;
queue<int> q;
q.push(t);
while(!q.empty()){
int x = q.front();
q.pop();
for(int i = G[x].size() - 1 ; i >= 0 ; i -- ){
edge& e = edges[G[x][i]^1];
if(d[e.from] < 0){
d[e.from] = d[e.to] + 1;
gap[d[e.from]] ++;
q.push(e.from);
}
}
}
return;
}
long long dfs(int to, long long flow){
if(to == t){
max_flow += flow;
return flow;
}
long long used = 0;
for(int i = G[to].size() - 1; i >=0 ;i-- ){
edge& e = edges[G[to][i]];
if(e.val > 0 && d[e.from] == d[e.to] + 1){
long long mi = dfs(e.to, min(e.val, flow - used));
if(mi){ // can be flowed out!
e.val -= mi;
edges[G[to][i]^1].val += mi;
used += mi;
if(e.from != s && e.to != t){
nxt[e.from] = e.to;
}
if(e.to != t && e.to > n)
tag[e.to - n] = 1;
}
if(used == flow)
return used;
}
}
gap[d[to]]--;
if(gap[d[to]] == 0)
d[1] = t + 1;
gap[++d[to]] ++;
return used;
}
long long ISAP(int s){
max_flow = 0;
bfs();
while(d[s] < t){
dfs(s, inf);
//printf("%d \n", max_flow);
}
for(int i = 1; i <= n; i++) {
if(!tag[i]) {
int u = i;
printf("%d ", u);
while(nxt[u] && nxt[u] != t) {
printf("%d ", nxt[u] - n);
u = nxt[u] - n;
}
cout << "\n";//puts("");
}
}
return max_flow;
}
HELLO WORLD
#include <iostream>
#include <vector>
#include <queue>
#include <algorithm>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
using namespace std;
int n, m;
int s, t;
struct edge{
int from, to;
long long val;
int cost;
edge(int f, int t, int v, int c = 1):from(f), to(t), val(v){
cost = c;
}
};
const int maxn = 200 * 2;
vector<edge> edges;
vector<int> G[maxn];
void addEdge(int from, int to, int val){
edges.push_back(edge(from, to, val, 1));
edges.push_back(edge(to, from, 0, -1));
int m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
return;
}
int pre[maxn];
long long flow[maxn];
int inq[maxn];
int d[maxn];
// for retracing the path
int nxt[maxn], tag[maxn];
const int inf = 1 << 30;
bool spfa(){
fill(flow, flow + maxn, inf);
fill(inq, inq + maxn, 0);
fill(d, d + maxn, inf);
queue<int> q;
q.push(s);
inq[s] = 1;
d[s] = 0;
while(!q.empty()){
int from = q.front(); q.pop();
inq[from] = 0;
for(int i = G[from].size() - 1 ; i >= 0 ; i-- ){
int to_index = G[from][i];
edge& e = edges[to_index];
if(e.val > 0 && d[e.from] + e.cost < d[e.to]){
// for traceback
pre[e.to] = to_index;
flow[e.to] = min(flow[e.from], e.val);
d[e.to] = d[e.from] + e.cost;
if(!inq[e.to]){
q.push(e.to);
inq[e.to] = 1;
}
}
}
}
return d[t]!=inf;;
}
void update(int& max_flow){
int cur = t;
int delta = flow[t];
while(cur != s){
// from t to s
int index = pre[cur];
edges[index].val -= delta;
edges[index^1].val += delta;
cur = edges[index^1].to;
// for last output
edge& e = edges[index];
if(e.from != s && e.to != t){
nxt[e.from] = e.to;
}
// if tagged <=> be tranversed <=> can't be the starting points
if(e.to != t && e.to > n)
tag[e.to - n] = 1;
}
max_flow += delta;
}
void EK(int& max_flow){
while(spfa()){
update(max_flow);
}
// for output
for(int i = 1; i <= n; i++) {
// find the start points
if(!tag[i]) {
int u = i;
printf("%d ", u);
// lets go ~
while(nxt[u] && nxt[u] != t) {
printf("%d ", nxt[u] - n);
u = nxt[u] - n;
}
cout << "\n";
}
}
}
int max_flow = 0;
int main(int argc, char** argv) {
freopen("1.txt", "r", stdin);
cin >> n >> m ;
s = n * 2 + 1;
t = n * 2 + 2;
for(int i = 1 ; i <= n ; i ++ ){
addEdge(s, i, 1);
addEdge(i + n, t, 1);
}
for(int i = 0 ; i < m ; i ++ ){
int from, to;
cin >> from >> to;
addEdge(from, to + n, 1);
}
EK(max_flow);
cout << n - max_flow << endl;
return 0;
}