結果
| 問題 | 
                            No.200 カードファイト!
                             | 
                    
| コンテスト | |
| ユーザー | 
                             koyumeishi
                         | 
                    
| 提出日時 | 2015-06-01 23:25:54 | 
| 言語 | C++11(廃止可能性あり)  (gcc 13.3.0)  | 
                    
| 結果 | 
                             
                                AC
                                 
                             
                            
                         | 
                    
| 実行時間 | 3 ms / 2,000 ms | 
| コード長 | 4,914 bytes | 
| コンパイル時間 | 973 ms | 
| コンパイル使用メモリ | 91,640 KB | 
| 実行使用メモリ | 6,820 KB | 
| 最終ジャッジ日時 | 2024-10-15 08:59:48 | 
| 合計ジャッジ時間 | 1,869 ms | 
| 
                            ジャッジサーバーID (参考情報)  | 
                        judge4 / judge3 | 
(要ログイン)
| ファイルパターン | 結果 | 
|---|---|
| sample | AC * 3 | 
| other | AC * 26 | 
ソースコード
#include <iostream>
#include <vector>
#include <cstdio>
#include <sstream>
#include <map>
#include <string>
#include <algorithm>
#include <queue>
#include <cmath>
#include <set>
using namespace std;
template<class T>
class Min_Cost_Flow{
public:
	struct edge{
		int to;
		int cap;
		T cost;
		int rev;
		bool reverse;
	};
	const T INF;
	vector<vector<edge>> G;
	Min_Cost_Flow(int n, T inf) : G(n), INF(inf){
	}
	void add_edge(int from, int to, int cap, T cost){
		G[from].push_back((edge){to, cap, cost, (int)G[to].size(), false});
		G[to].push_back((edge){from, 0, -cost, (int)G[from].size()-1, true});
	}
	//min cost : s->t (flow:f)
	T min_cost_flow(int s, int t, int f){
		T cost = 0;
		vector<int> prev_v(G.size(),-1);
		vector<int> prev_e(G.size(),-1);
		vector<T> potantial(G.size(), 0);
		vector<T> dist(G.size(), INF);
		dist[s] = 0;
		/*bellman_ford*/{
			bool update = true;
			for(int cnt = 0; update; cnt++){
				update = false;
				for(int i=0; i<G.size(); i++){
					if(dist[i] >= INF) continue;
					for(int j=0; j<G[i].size(); j++){
						if(G[i][j].cap > 0 && dist[G[i][j].to] > dist[i] + G[i][j].cost){
							dist[G[i][j].to] = dist[i] + G[i][j].cost;
							update = true;
						}
					}
				}
				if(update && cnt >= G.size()){
					cerr << " there is a negative cycle " << endl;
					return -1;
				}
				cnt++;
			}
			for(int i=0; i<G.size(); i++){
				potantial[i] = dist[i];
			}
		}
		while(f>0){
			fill(dist.begin(), dist.end(), INF);
			dist[s] = 0;
			prev_v[s] = s;
			/*dijkstra*/{
				priority_queue<pair<T,int>, vector<pair<T,int>>, greater<pair<T,int>>> pq;
				pq.push({0, s});
				while(pq.size()){
					pair<T, int> p = pq.top(); pq.pop();
					if(dist[p.second] < p.first) continue;
					dist[p.second] = p.first;
					for(int i=0; i<G[p.second].size(); i++){
						edge& e = G[p.second][i];
						T new_dist = dist[p.second] + e.cost + potantial[p.second] - potantial[e.to];
						if(e.cap > 0 && dist[e.to] > new_dist){
							dist[e.to] = new_dist;
							prev_v[e.to] = p.second;
							prev_e[e.to] = i;
							pq.push({dist[e.to], e.to});
						}
					}
				}
			}
			if(potantial[t] + dist[t] == INF){
				cerr << "couldn't insert flow f : " << f << endl;
				return -1;
			}
			for(int i=0; i<G.size(); i++){
				potantial[i] += dist[i];
			}
			int d = f;
			int pos = t;
			while(pos != s){
				int v = prev_v[pos];
				int e = prev_e[pos];
				d = min(d, G[v][e].cap);
				pos = prev_v[pos];
			}
			pos = t;
			while(pos != s){
				int v = prev_v[pos];
				int e = prev_e[pos];
				G[v][e].cap -= d;
				G[G[v][e].to][G[v][e].rev].cap += d;
				pos = v;
			}
			cost += d * potantial[t];	//potential is new_dist
			f -= d;
			//f==0 then end
		}
		return cost;
	}
	vector<vector<int>> get_edge_info(){
		vector<vector<int>> E(G.size());
		for(int i=0; i<G.size(); i++){
			for(int j=0; j<G[i].size(); j++){
				edge& e = G[i][j];
				if(e.reverse) continue;
				edge& rev_e = G[e.to][e.rev];
				if(e.cap == 0){
					E[i].push_back(e.to);
				}
			}
		}
		return E;
	}
};
int main(){
	int n;
	cin >> n;
	int x;
	cin >> x;
	vector<int> a(x);
	for(int i=0; i<x; i++){cin>>a[i];}
	random_shuffle(a.begin(), a.end());
	int y;
	cin >> y;
	vector<int> b(y);
	for(int i=0; i<y; i++){cin>>b[i];}
	random_shuffle(b.begin(), b.end());
	int sz_x = (n/x + (n%x==0?0:1)) * x;
	int sz_y = (n/y + (n%y==0?0:1)) * y;
	
	int sz = sz_x + sz_y + 2;
	int s = sz_x + sz_y + 0;
	int t = sz_x + sz_y + 1;
	Min_Cost_Flow<int> flow(sz, 1e8);
	vector<long long> offset_x;
	for(int k=0; k<sz_x/x; k++){
		for(int i=0; i<x; i++){
			long long cost = 100000 + 10*k;
			flow.add_edge(s, i + x*k, 1, cost);
			offset_x.push_back(cost);
		}
	}
	vector<long long> offset_y;
	for(int k=0; k<sz_y/y; k++){
		for(int i=0; i<y; i++){
			long long cost = 100000 + 10*k;
			flow.add_edge( sz_x + i + y*k, t, 1, cost);
			offset_y.push_back(cost);
		}
	}
	for(int i=0; i<sz_x; i++){
		for(int j=sz_x; j<sz_x+sz_y; j++){
			int l = ( ( (i/x)*x)/y)*y;
			int r = (((i/x + 1)*x - 1)/y + 1)*y;
			if( j-sz_x < l || r <= j-sz_x) continue;
			flow.add_edge( i, j, 1, (a[i%x]>b[(j-sz_x)%y]?0:1) );
		}
	}
	long long ans = 0;
	for(int i=0; i<n; i++){
		ans -= offset_x[i] + offset_y[i];
	}
	ans += flow.min_cost_flow(s,t, n);
	
	ans = n - ans;
	cout << ans << endl;
/*
	
	cerr << s << " " << t << endl;
	auto e = flow.get_edge_info();
	map<int, vector<int>> v;
	for(int i=0; i<e.size(); i++){
		if(i == s || i == t) continue;
		if(i >= sz_x) continue;
		for(int j=0; j<e[i].size(); j++){
			if(e[i][j] == s || e[i][j] == t) continue;
			cerr << i << " -> " << e[i][j]-sz_x << " : ";
			cerr << a[i%x] << " -> " << b[(e[i][j]-sz_x)%y] << endl;
			v[a[i%x]].push_back(b[(e[i][j]-sz_x)%y]);
		}
	}
	for(int i=0; i<x; i++){
		cerr << a[i] << " ";
		for(auto itr = v[a[i]].begin(); itr != v[a[i]].end(); itr++){
			cerr << *itr << " ";
		}cerr << endl;
	}
*/
	return 0;
}
            
            
            
        
            
koyumeishi