Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #pragma GCC optimize ("O3")
- #pragma GCC target ("sse4")
- #include <bits/stdc++.h>
- #include <ext/pb_ds/assoc_container.hpp>
- #include <ext/pb_ds/tree_policy.hpp>
- using namespace std;
- template <class T>
- using ordered_set = __gnu_pbds::tree<T, __gnu_pbds::null_type, less<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
- template <class T>
- using ordered_multiset = __gnu_pbds::tree<T, __gnu_pbds::null_type, less_equal<T>, __gnu_pbds::rb_tree_tag, __gnu_pbds::tree_order_statistics_node_update>;
- #define PI atan2(0, -1)
- #define epsilon 1e-9
- #define INF 5e18
- #define MOD 1000000007
- #define mp make_pair
- #define pb push_back
- #define f first
- #define s second
- #define lb lower_bound
- #define ub upper_bound
- struct Edge{
- long long v, flow, C, rev;
- };
- struct Dinic {
- long long level [2050], start [2050], cache [2050];
- vector<Edge> adj [2050];
- void addEdge(int u, int v, long long C){
- Edge a{v, 0, C, (long long)adj[v].size()};
- Edge b{u, 0, 0, (long long)adj[u].size()};
- adj[u].pb(a); adj[v].pb(b);
- }
- bool BFS(int s, int t){
- for(int i = 0; i < 2050; i++) level[i] = -1;
- queue<int> q; level[s] = 0; q.push(s);
- while(!q.empty()){
- int u = q.front(); q.pop();
- for(auto e: adj[u])
- if(level[e.v] < 0 && e.flow < e.C){
- level[e.v] = level[u]+1;
- q.push(e.v);
- }
- }
- return level[t] != -1;
- }
- long long sendFlow(int u, long long flow, int t){
- if(u == t) return flow;
- for( ; start[u] < adj[u].size(); start[u] ++){
- Edge &e = adj[u][start[u]];
- if(level[e.v] == level[u]+1 && e.flow < e.C){
- long long curr_flow = min(flow, e.C-e.flow);
- long long temp_flow = sendFlow(e.v, curr_flow, t);
- if(temp_flow > 0){
- e.flow += temp_flow;
- adj[e.v][e.rev].flow -= temp_flow;
- return temp_flow;
- }
- }
- }
- return 0;
- }
- long long flowIt(int s, int t){
- if(s == t) return -1;
- long long total = 0;
- while(BFS(s, t)){
- for(int i = 0; i < 2050; i++) start[i] = 0;
- while (long long flow = sendFlow(s, INF, t)) total += flow;
- }
- return total;
- }
- };
- int N, M, processed = 0, indeg [510];
- vector<int> adjacency [510];
- bool linked [510][510];
- queue<int> q;
- Dinic solver;
- int main(){
- //freopen("sort.in", "r", stdin); freopen("sort.out", "w", stdout);
- ios_base::sync_with_stdio(0); cin.tie(0); cout << fixed << setprecision(10);
- cin >> N >> M;
- for(int i = 0; i < M; i++){
- int a, b; cin >> a >> b;
- adjacency[a].pb(b); indeg[b]++;
- linked[a][b] = 1;
- }
- for(int k = 0; k < N; k++)
- for(int a = 0; a < N; a++)
- for(int b = 0; b < N; b++)
- linked[a][b] |= linked[a][k]&linked[k][b];
- for(int i = 0; i < N; i++)
- if(indeg[i] == 0)
- q.push(i);
- while(q.size() > 0){
- int curr = q.front(); q.pop();
- processed++;
- for(int nexty : adjacency[curr])
- if(--indeg[nexty] == 0)
- q.push(nexty);
- }
- for(int i = 0; i < N; i++)
- if(indeg[i])
- for(int j = 0; j < N; j++)
- linked[i][j] = linked[j][i] = 0;
- for(int i = 0; i < N; i++){
- solver.addEdge(1000, i, 1), solver.addEdge(i+N, 1001, 1);
- for(int j = 0; j < N; j++)
- if(linked[i][j])
- solver.addEdge(i, j+N, 1);
- }
- cout << processed-solver.flowIt(1000, 1001) << '\n';
- return 0;
- }
- /******************************
- Kateba ii dake no hanashi darou
- Success is only a victory away
- - No Game No Life Opening
- ******************************/
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement