Submission #134471

#TimeUsernameProblemLanguageResultExecution timeMemory
134471model_codeVirus Experiment (JOI19_virus)C++17
100 / 100
838 ms120684 KiB
#include <iostream>
#include <cstdio>
#include <string>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;

typedef pair<int,int> P;

char dir[4] = { 'E' , 'N' , 'W' , 'S' };
int di[4][2] = { {0,1},{-1,0},{0,-1},{1,0} };

#define rep(i,x) for(int i=0;i<x;i++)
#define rep1(i,x) for(int i=1;i<=x;i++)

const int MAX_V = 800*800+10;
struct Graph{
	int V;
	vector<int> G[MAX_V];
	vector<int> rG[MAX_V];
	
	void init(int V_){
		V = V_;
		for(int i = 0 ; i < V_ ; i ++){
			G[i].clear();
			rG[i].clear();
		}
	}
	
	void add_edge(int from,int to){
		G[from].push_back(to);
		rG[to].push_back(from);
	}
	
	int cmp[MAX_V];
	vector<int> vs;
	bool used[MAX_V];
	void dfs(int v){
		used[v] = true;
		for(int i = 0 ; i < G[v].size() ; i ++){
			if(!used[G[v][i]])dfs(G[v][i]);
		}
		vs.push_back(v);
	}
	void rdfs(int v,int k){
		used[v] = true;
		cmp[v] = k;
		for(int i = 0 ; i < rG[v].size() ; i ++){
			if(!used[rG[v][i]])rdfs(rG[v][i],k);
		}
	}
	int scc(){
		for(int i = 0 ; i < V ; i ++){
			used[i] = false;
		}
		vs.clear();
		for(int i = 0 ; i < V ; i ++){
			if(!used[i])dfs(i);
		}
		for(int i = 0 ; i < V ; i ++){
			used[i] = false;
		}
		int k = 0;
		for(int i = (int)vs.size()-1 ; i >= 0 ; --i){
			if(!used[vs[i]])rdfs(vs[i],k++);
		}
		return k;
	}
	
	int end[MAX_V];
	int end_cmp(int v){
		if(end[v] != -1)return end[v];
		for(int i = 0 ; i < G[v].size() ; i ++){
			if(cmp[G[v][i]] != cmp[v])return end[v] = end_cmp(G[v][i]);
		}
		return end[v] = cmp[v];
	}
}G;

int main(){
	static int n,r,c;
	static string d;
	static int u[802][802];
	scanf("%d%d%d",&n,&r,&c);
	cin >> d;
	for(int i = 1 ; i <= r ; i ++){
		for(int j = 1 ; j <= c ; j ++){
			scanf("%d",&u[i][j]);
			if(u[i][j] == 0)u[i][j] = 100001;
		}
	}
	
	int v[1<<4] = {};
	for(int i = 0 ; i < (1<<4) ; i ++){
		static bool b[100010];
		int cnt = 0;
		for(int j = 0 ; j < d.size() ; j ++){
			b[j] = false;
			for(int k = 0 ; k < 4 ; k ++){
				b[j] |= d[j] == dir[k] && ((i>>k)&1);
			}
			if(b[j])cnt ++;
			else cnt = 0;
			v[i] = max( v[i] , cnt );
		}
		if(cnt != d.size() && b[0] && b[d.size()-1]){
			cnt = 0;
			for(int i = 0 ; b[i] ; i ++)cnt ++;
			for(int i = d.size()-1 ; b[i] ; i --)cnt ++;
			v[i] = max( v[i] , cnt );
		}
		if(v[i] == d.size())v[i] = 100000;
	}
	
	static vector<P> cand;
	static int a[802][802] = {};
	static P rel[MAX_V] = {};
	static P rel_[MAX_V] = {};
	for(int i = 1 ; i <= r ; i ++){
		for(int j = 1 ; j <= c ; j ++){
			a[i][j] = (i-1)*c+j;
			rel[(i-1)*c+j] = P(i,j);
		}
	}
	static int k = r*c;
	static int num[MAX_V];
	static int ler[MAX_V];
	static int nn[MAX_V];
	while(k >= 1){
		G.init(k+1);
		for(int i = 1 ; i <= r ; i ++){
			for(int j = 1 ; j <= c ; j ++){
				for(int s = 0 ; s < 4 ; ++s){
					int id = a[i+di[s][0]][j+di[s][1]];
					if(id <= 0 || id == abs(a[i][j]))continue;
					int x = 0;
					for(int t = 0 ; t < 4 ; ++t){
						if(a[i+di[t][0]][j+di[t][1]] == id){
							x += 1<<t;
						}
					}
					if(v[x] >= u[i][j]){
						G.add_edge(id,abs(a[i][j]));
					}
				}
			}
		}
		for(int i = 1 ; i <= k ; i ++){
			if(G.G[i].size() == 0){
				cand.push_back(rel[i]);
				G.add_edge(i,0);
			}
		}
		
		int k_ = G.scc();
		for(int i = 0 ; i <= k ; i ++){
			G.end[i] = -1;
		}
		
		/*for(int i = 0 ; i <= k ; i ++){
			cout << G.cmp[i] << ":" << G.end_cmp(i) << endl;
		}*/
		
		int cnt = 0;
		vector<int> endcmp;
		for(int i = 1 ; i <= k ; i ++){
			if(G.cmp[i] == G.end_cmp(i)){
				endcmp.push_back(G.cmp[i]);
			}
		}
		sort(endcmp.begin(),endcmp.end());
		endcmp.erase(unique(endcmp.begin(),endcmp.end()),endcmp.end());
		cnt = endcmp.size();
		nn[G.cmp[0]] = 0;
		for(int i = 0 ; i < cnt ; i ++){
			nn[endcmp[i]] = i+1;
		}
		for(int i = 0 ; i <= k ; i ++){
			if(G.cmp[i] == G.end_cmp(i)){
				num[i] = nn[G.cmp[i]];
				ler[num[i]] = i;
			}
		}
		for(int i = 0 ; i <= k ; i ++){
			if(G.cmp[i] != G.end_cmp(i)){
				num[i] = -nn[G.end_cmp(i)];
			}
		}
		k = cnt;
		for(int i = 1 ; i <= k ; i ++){
			rel_[i] = rel[ler[i]];
		}
		for(int i = 1 ; i <= k ; i ++){
			rel[i] = rel_[i];
		}
		for(int i = 1 ; i <= r ; i ++){
			for(int j = 1 ; j <= c ; j ++){
				if(a[i][j] < 0)a[i][j] = -abs(num[-a[i][j]]);
				else a[i][j] = num[a[i][j]];
			}
		}
		
		queue<P> que;
		for(int i = 1 ; i <= r ; i ++){
			for(int j = 1 ; j <= c ; j ++){
				que.push(P(i,j));
			}
		}
		while(!que.empty()){
			P p = que.front(); que.pop();
			int i = p.first;
			int j = p.second;
			if(a[i][j] >= 0)continue;
			if(i == 0 || i == r+1 || j == 0 || j == c+1)continue;
			int s = 0;
			rep(k,4)if(a[i+di[k][0]][j+di[k][1]] == -a[i][j])s += 1<<k;
			if(v[s] >= u[i][j]){
				a[i][j] = -a[i][j];
				rep(k,4)que.push(P(i+di[k][0],j+di[k][1]));
			}
		}
	}
	
	static int ret = r*c;
	static int ret_cnt = 0;
	static bool used[802][802];
	rep(i,802)rep(j,802)used[i][j] = false;
	for(int i = 0 ; i < cand.size() ; i ++){
		int x = cand[i].first;
		int y = cand[i].second;
		if(u[x][y] == 100001)continue;
		vector<P> vec;
		queue<P> que;
		rep(k,4){
			que.push(P(x+di[k][0],y+di[k][1]));
		}
		used[x][y] = true;
		vec.push_back(P(x,y));
		while(!que.empty()){
			P p = que.front(); que.pop();
			int i = p.first;
			int j = p.second;
			if(i == 0 || i == r+1 || j == 0 || j == c+1 || used[i][j])continue;
			int s = 0;
			rep(k,4)if(used[i+di[k][0]][j+di[k][1]])s += 1<<k;
			if(v[s] >= u[i][j]){
				used[i][j] = true;
				vec.push_back(p);
				rep(k,4)que.push(P(i+di[k][0],j+di[k][1]));
			}
		}
		for(int i = 0 ; i < vec.size() ; i ++){
			used[vec[i].first][vec[i].second] = false;
		}
		if(vec.size() < ret){
			ret = vec.size();
			ret_cnt = 1;
		}
		else if(vec.size() == ret){
			ret_cnt ++;
		}
	}
	cout << ret << endl << ret_cnt*ret << endl;
}

Compilation message (stderr)

virus.cpp: In member function 'void Graph::dfs(int)':
virus.cpp:41:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for(int i = 0 ; i < G[v].size() ; i ++){
                   ~~^~~~~~~~~~~~~
virus.cpp: In member function 'void Graph::rdfs(int, int)':
virus.cpp:49:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for(int i = 0 ; i < rG[v].size() ; i ++){
                   ~~^~~~~~~~~~~~~~
virus.cpp: In member function 'int Graph::end_cmp(int)':
virus.cpp:74:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for(int i = 0 ; i < G[v].size() ; i ++){
                   ~~^~~~~~~~~~~~~
virus.cpp: In function 'int main()':
virus.cpp:98:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for(int j = 0 ; j < d.size() ; j ++){
                   ~~^~~~~~~~~~
virus.cpp:107:10: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   if(cnt != d.size() && b[0] && b[d.size()-1]){
      ~~~~^~~~~~~~~~~
virus.cpp:113:11: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   if(v[i] == d.size())v[i] = 100000;
      ~~~~~^~~~~~~~~~~
virus.cpp:156:7: warning: unused variable 'k_' [-Wunused-variable]
   int k_ = G.scc();
       ^~
virus.cpp:229:20: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
  for(int i = 0 ; i < cand.size() ; i ++){
                  ~~^~~~~~~~~~~~~
virus.cpp:253:21: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   for(int i = 0 ; i < vec.size() ; i ++){
                   ~~^~~~~~~~~~~~
virus.cpp:256:17: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   if(vec.size() < ret){
      ~~~~~~~~~~~^~~~~
virus.cpp:260:22: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
   else if(vec.size() == ret){
           ~~~~~~~~~~~^~~~~~
virus.cpp:85:7: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
  scanf("%d%d%d",&n,&r,&c);
  ~~~~~^~~~~~~~~~~~~~~~~~~
virus.cpp:89:9: warning: ignoring return value of 'int scanf(const char*, ...)', declared with attribute warn_unused_result [-Wunused-result]
    scanf("%d",&u[i][j]);
    ~~~~~^~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...