stablegradients/pie-gem5-bysrc huggingface dataset:
// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;



const int MAX = 2 * pow(10, 5);

const int VISITED = 1;

const int UNVISITED = 0;

int color[MAX];

vector<vector<int>> G(MAX); //connected list G



int dfs(int r){

  stack<int> S;

  S.push(r);

  int num = 1;

  color[r] = VISITED;

  while(!S.empty()){

    int u = S.top();

    S.pop();

    for(int i = 0; i < G[u].size(); i++){

      int v = G[u][i];

      if(color[v] == UNVISITED){

        color[v] = VISITED;

        S.push(v);

        num += 1;

      }

    }

  }

  return num;

}







int main(){

  int N;

  int M;

  cin >> N >> M;

  vector<int> A(M);

  vector<int> B(M);

  for(int i = 0; i < M; i++){

    cin >> A[i]>> B[i];

  }

  

  for(int i = 0; i < M; i++){

    G[A[i] - 1].push_back(B[i] - 1);

    G[B[i] - 1].push_back(A[i] - 1);

  }

  

  for(int i = 0; i < N; i++){

    sort(G[i].begin(), G[i].end());

    color[i] = UNVISITED;

  }

  

  int ans = 0;

  for(int i = 0; i < N; i++){

    if(color[i] == UNVISITED){

      ans = max(ans, dfs(i));

    }

  }

  cout << ans << endl;

  

  return 0;

}

// Optimized solution to the same problem (faster):
#include <iostream>

#include <vector>

#include <algorithm>

using namespace std;



struct UnionFind {

  vector<int> r;

  

  UnionFind(int N){

    r = vector<int>(N, -1);

  }

  

  int root(int x){

    if(r[x] < 0) return x;

    return r[x] = root(r[x]);

  }

  

  bool unite(int x, int y){

    x = root(x);

    y = root(y);

    if(x == y) return false;

    if(r[x] > r[y]) swap(x, y);

    r[x] += r[y];

    r[y] = x;

    return true;

  }

  

  int size(int x){

    return -r[root(x)];

  }

};



int main(){

  int N, M;

  cin >> N >> M;

  

  UnionFind UF(N);

  for(int i = 0; i < M; i++){

    int A, B;

    cin >> A >> B;

    UF.unite(A - 1, B - 1);

  }

  int ans = 0;

  for(int i = 0; i < N; i++){

    ans = max(ans, UF.size(i));

  }

  cout << ans << endl;

  

  return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

using P = pair<int, int>;

#define rep(i, n) for (int i = 0; i < (n); ++i)

vector<int> p(200000);

vector<int> sz(200000);





int find(int x)

{

    while (p[x] != x) {

        p[x] = p[p[x]];

        x = p[x];

    }

    return x;

}



void merge(int x, int y)

{

    int a = find(x);

    int b = find(y);

    if (a == b) return;

    if (sz[a] < sz[b]) {

        p[a] = b;

        sz[b] += sz[a];

    } else {

        p[b] = a;

        sz[a] += sz[b];

    }

}



int main()

{

    int n, m;

    cin >> n >> m;

    rep(i, n) {

        p[i] = i;

        sz[i] = 1;

    }

    rep(i, m) {

        int x, y;

        cin >> x >> y;

        merge(x-1, y-1);

    }

    int ans = 0;

    vector<int> counter(n);

    rep(i, n) counter[find(p[i])]++;

    rep(i, n) ans = max(counter[i], ans);

    cout << ans << endl;

    return 0;

}

// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

using P = pair<int, int>;

#define rep(i, n) for(int i = 0; i < (n); ++i)



struct UnionFind {

    vector<int> d;

    UnionFind(int n=0):d(n,-1){}

    int find(int x) {

        if (d[x] < 0) return x;

        return d[x] = find(d[x]);

    }

    bool unite(int x, int y) {

        x = find(x); y = find(y);

        if (x == y) return false;

        if (d[x] > d[y]) swap(x, y);

        d[x] += d[y];

        d[y] = x;

        return true;

    }

    bool same(int x, int y) {return find(x) == find(y);}

    int size(int x) {return -d[find(x)];}

};



int main()

{

    int n, m;

    cin >> n >> m;

    UnionFind uf(n);

    rep(i,m) {

        int a, b;

        cin >> a >> b;

        --a; --b;

        uf.unite(a, b);

    }

    int ans = 0;

    rep(i,n) ans = max(ans, uf.size(i));

    cout << ans << endl;

    return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <iostream>

#include <vector>

using namespace std;

const int MAX_N = 200001;

int n, m;

vector<int> G[MAX_N]; //隣接リスト;

bool used[MAX_N]; //訪問済みかどうか



int dfs(int v) {

  used[v] = true;

  int sum = 1;

  for (int i = 0; i < G[v].size(); i++) {

    if (!used[G[v][i]]) {

      sum += dfs(G[v][i]);

    }

  }

  return sum;

}



int main() {

  cin >> n >> m;

  for (int i = 0; i < m; i++) {

    int a, b;

    cin >> a >> b;

    //辺を張る

    G[a].push_back(b);

    G[b].push_back(a);

  }

  

  // 全てを点を試す

  int ans = 0;

  int res = 0;

  for (int i = 0; i < n; i++) {

    res = dfs(i);

    ans = max(ans, res);

  }

  

  cout << ans;

}

// Optimized solution to the same problem (faster):
#include <iostream>

#include <vector>

using namespace std;



int n, m;



struct UnionFind {

  vector<int> r;

  UnionFind(int N) {

    r = vector<int>(N, -1);

  }

  

  int root(int x) {

    if (r[x] < 0) return x;

    return r[x] = root(r[x]);

  }

 

  bool unite(int x, int y) {

    x = root(x);

    y = root(y);

    if (x == y) return false;

    if (r[x] > r[y]) swap(x, y);

    r[x] += r[y];

    r[y] = x;

    return true;

  }

  

  int size(int x) {

    return -r[root(x)];

  }

};



int main() {

  cin >> n >> m;

  UnionFind UF(n);

  for (int i = 0; i < m; i++) {

    int A, B;

    cin >> A >> B;

    UF.unite(A, B);

  }

  

  int ans = 0;

  for (int i = 0; i < n; i++) {

    ans = max(ans, UF.size(i));

  }

  cout << ans;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <iostream>

#include <vector>

using namespace std;



const int MAX_N = 200000;

int n, m;

vector<vector<int>> G(MAX_N); //隣接リスト

bool used[MAX_N]; // 訪問済みかどうか



int dfs(int v) {

  used[v] = true;

  

  int d = 1;

  for (int i = 0; i < G[v].size(); i++) {

    int next = G[v][i];

    if (!used[next]) {

      d += dfs(next);

    }

  }

  return d;

}



int main() {

  cin >> n >> m;

  for (int i = 0; i < m; i++) {

    int a, b;

    cin >> a >> b;

    --a; --b;

    // 辺を張る

    G[a].push_back(b);

    G[b].push_back(a);

  }

  

  int ans = 0;

  for (int i = 0; i < n; i++) {

    int d = dfs(i);

    ans = max(ans, d);

  }

  

  cout << ans;

}

// Optimized solution to the same problem (faster):
#include <iostream>

#include <vector>

using namespace std;



int n, m;



struct UnionFind {

  vector<int> r;

  UnionFind(int N) {

    r = vector<int>(N, -1);

  }

  

  int root(int x) {

    if (r[x] < 0) return x;

    return r[x] = root(r[x]);

  }

 

  bool unite(int x, int y) {

    x = root(x);

    y = root(y);

    if (x == y) return false;

    if (r[x] > r[y]) swap(x, y);

    r[x] += r[y];

    r[y] = x;

    return true;

  }

  

  int size(int x) {

    return -r[root(x)];

  }

};



int main() {

  cin >> n >> m;

  UnionFind UF(n);

  for (int i = 0; i < m; i++) {

    int A, B;

    cin >> A >> B;

    UF.unite(A, B);

  }

  

  int ans = 0;

  for (int i = 0; i < n; i++) {

    ans = max(ans, UF.size(i));

  }

  cout << ans;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;



int cnt;

vector<vector<int>> G(3e5);

vector<int> seen(3e5,false);



void dfs(int u) {

  seen[u]=true;

  cnt++;

  for(int next:G[u]) if(seen[next]==false) dfs(next);

}



int main() {

  int n,m; cin>>n>>m;

  int a,b,ans=0;

  for(int i=0;i<m;i++) {

    cin>>a>>b;

    G[a].push_back(b);

    G[b].push_back(a);

  }

  for(int i=1;i<=n;i++) {

    if(seen[i]==false) {

      cnt=0;

      dfs(i);

    }

    ans=max(ans,cnt);

  }

  cout<<ans<<endl;

}


// Optimized solution to the same problem (faster):
#include<bits/stdc++.h>

using namespace std;



vector<vector<int>> G(3e5);

vector<bool> seen(3e5,false);

int cnt;



void bfs(int r) {

  queue<int> Q;

  Q.push(r);

  seen[r]=true;

  int u;

  while(!Q.empty()) {

    u=Q.front();

    Q.pop();

    cnt++;

    for(int next:G[u]) {

      if(seen[next]==false) {

        seen[next]=true;

        Q.push(next);

      }

    }

  }

}



int main() {

  int n,m; cin>>n>>m;

  int a,b,ans=0;

  for(int i=0;i<m;i++) {

    cin>>a>>b;

    G[a].push_back(b);

    G[b].push_back(a);

  }

  for(int i=1;i<=n;i++) {

    if(seen[i]==false) {

      cnt=0;

      bfs(i);

      ans=max(ans,cnt);

    }

  }

  cout<<ans<<endl;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
//#include<bits/stdc++.h>

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<iostream>

#include<stdlib.h>

#include<queue>

#include<map>

#include<vector>

#include<cmath>

#include<fstream>

#include <set>

//freopen(".in","r",stdin);

//freopen(".out","w",stdout);

//freopen("input.txt","r",stdin);

//freopen("output.txt","w",stdout);

const int  MAXN =2e5+10;

const int mod = 1e9 + 7;

const long long INF = 0x7f7f7f7f7f7f7f7f;

const int inf= 0x3f3f3f3f;

#define eps 1e-8

#define PI 3.1415926535898

#define lowbit(x) (x&(-x))

using namespace std ;

//getline(cin,s);

//set<ll>::iterator it;

//map<int,int>::iterator it;

//unordered_map

typedef long long ll;

int vis[MAXN],dist[MAXN];

vector<int>ve[MAXN];

void dfs(int now)

{

	if(vis[now]) return ;

	vis[now]=1;

	for(int i=0;i<ve[now].size();i++)

	{

		int ne=ve[now][i];

		if(!vis[ne])

		{

			dfs(ne);

			dist[now]+=dist[ne];

		}

	}

	return ;

}

int main()

{

	int n,m,ans=0;

	scanf("%d %d",&n,&m);

	for(int i=1;i<=n;i++) dist[i]=1;

	while(m--)

	{

		int x,y;

		scanf("%d %d",&x,&y);

		ve[x].push_back(y);

		ve[y].push_back(x);

	}

	for(int i=1;i<=n;i++)

	{

		if(!vis[i])

		{

		    dfs(i);

		    ans=max(ans,dist[i]);

		} 

	}

	printf("%d\n",ans);

	return 0;

}

// Optimized solution to the same problem (faster):
//#include<bits/stdc++.h>

#include<cstdio>

#include<cstring>

#include<algorithm>

#include<iostream>

#include<stdlib.h>

#include<queue>

#include<map>

#include<vector>

#include<cmath>

#include<fstream>

#include <set>

//freopen(".in","r",stdin);

//freopen(".out","w",stdout);

//freopen("input.txt","r",stdin);

//freopen("output.txt","w",stdout);

const int  MAXN =2e5+10;

const int mod = 1e9 + 7;

const long long INF = 0x7f7f7f7f7f7f7f7f;

const int inf= 0x3f3f3f3f;

#define eps 1e-8

#define PI 3.1415926535898

#define lowbit(x) (x&(-x))

using namespace std ;

//getline(cin,s);

//set<ll>::iterator it;

//map<int,int>::iterator it;

//unordered_map

typedef long long ll;

//已AC 尝试去并查集 

int father[MAXN];

int need[MAXN];

int Find(int x)

{

	return x==father[x] ? x : father[x]= Find(father[x]);

}

int main()

{

	int n,m;

	scanf("%d %d",&n,&m);

	for(int i=1;i<=n;i++) father[i]=i,need[i]=1;

	while(m--)

	{

		int a,b;

		scanf("%d %d",&a,&b);

		int x=Find(a),y=Find(b);

		if(x!=y)

		{

			father[x]=y;

			need[y]+=need[x];

		}

	}

	int ans=0;

	for(int i=1;i<=n;i++)

	{

		ans=max(ans,need[i]);

	}

	//for(int i=1;i<=n;i++) printf("need: %d\n",need[i]);

	printf("%d\n",ans);

	return 0;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

#define rep(i, n) for (int i = 0; i < (int)(n); i++)

#define P pair<ll,ll>



vector<int> to[200010];



void dfs(int i, int &gr, vector<int> &group){

  if(group[i]!=-1) return;

  group[i]=gr;

  for(auto x : to[i]){

    dfs(x,gr,group);

  }

}



int main(){

  int n,m;

  cin>>n>>m;

  rep(i,m){

    int a,b;

    cin>>a>>b;

    a--;b--;

    to[a].push_back(b);

    to[b].push_back(a);

  }

  vector<int> group(n);

  rep(i,n) group[i]=-1;

  int tmp=0;

  rep(i,n){

    if(group[i]==-1){

      dfs(i,tmp,group);

      tmp++;

    }

  }

  map<int,int> mp;

  rep(i,n){

    mp[group[i]]++;

  }

  int ans=0;

  for(auto x : mp){

    ans=max(ans,x.second);

  }

  cout<<ans<<endl;

}

// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

#define rep(i, n) for (int i = 0; i < (int)(n); i++)

#define P pair<ll,ll>



class UnionFind {

    vector<int> data;

    ll num;

public:

    UnionFind(int size) : data(size, -1), num(size) { }

    bool unite(int x, int y) {//xとyの集合を統合する

        x = root(x); y = root(y);

        if (x != y) {

            if (data[y] < data[x]) swap(x, y);

            data[x] += data[y]; data[y] = x;

        }

        num -= (x != y);

        return x != y;

    }

    bool findSet(int x, int y) {//xとyが同じ集合か返す

        return root(x) == root(y);

    }

    int root(int x) {//xのルートを返す

        return data[x] < 0 ? x : data[x] = root(data[x]);

    }

    ll size(int x) {//xの集合のサイズを返す

        return -data[root(x)];

    }

    ll numSet() {//集合の数を返す

        return num;

    }

};





int main(){

  int n,m;

  cin>>n>>m;

  UnionFind uf(n);

  rep(i,m){

    int a,b;

    cin>>a>>b;

    a--;b--;

    uf.unite(a,b);

  }

  ll ans=0;

  rep(i,n) ans=max(ans,uf.size(i));

  cout<<ans<<endl;



}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>



#define pb push_back

#define mp make_pair

#define ff first

#define ss second

#define all(x) (x).begin(), (x).end()

#define ll long long

#define ii pair<int,int>

#define vi vector<int>

#define vll vector<ll>

#define vii vector<ii>



const int INF = 0x3f3f3f3f;

const ll  LINF = 0x3f3f3f3f3f3f3f3fLL;

const int maxn = 2e5+10;

const int mod = 1e9+7;



using namespace std;



int p[maxn],sz[maxn],qtd;



void start(){

    for(int i=0;i<maxn;++i){

        p[i] = i;

        sz[i] = 1;

    }

}



int find_set(int x){

    return p[x] = (p[x] == x ? x : find_set(p[x])); 

}



int same_set(int x,int y){

    return find_set(x) == find_set(y);

}



void union_set(int a,int b){

    a = find_set(a);

    b = find_set(b);

    if(a==b) return;

    if(sz[a] > sz[b]) swap(a,b);

    p[a] = b;

    sz[b]+=sz[a];

}



void solve(){

    int n,m;

    cin >> n >> m;

    while(m--){

        int x,y;

        cin >> x >> y;

        union_set(x,y);

    }

    for(int i=1;i<=n;++i){

        if(p[i] == i){

            qtd=max(qtd,sz[i]);

        }

    }

    cout << qtd << endl;

}



int32_t main(){

    ios_base::sync_with_stdio(false);

    cin.tie(0);

    cout.tie(0);



    start();



    int t = 1;



    // cin >> t;



    while(t--){

        solve();

    }



    return 0;

}

// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

#define ll long long

using namespace std;

const ll mod=1e9+7;

int f[200005]={0};

int sz[200005]={0};

int n,m;

int ans=1;

int get(int x)

{

	if(x==f[x])return x;

	return f[x]=get(f[x]);

}

void merge(int x,int y)

{

	int xx=get(x);

	int yy=get(y);

	if(xx!=yy){

		f[xx]=yy;

		sz[yy]+=sz[xx];

		ans=max(ans,sz[yy]);

	}

	

}

void init()

{

	for(int i=1;i<=n;i++){

		f[i]=i;

		sz[i]=1;

	}

}

int main(){

    cin>>n>>m;

    init();

    while(m--){

    	int x,y;

    	cin>>x>>y;

    	merge(x,y);

	}

	cout<<ans<<endl;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

#define ss second

#define ff first

#define all(x) x.begin(), x.end()



using namespace std;

using ll = long long;

using pii = pair<ll, ll>;



const ll oo = 1e18 + 7;

const ll mod = 1e9 + 7, maxn = 2e5 + 10;  

const long double PI = acos(-1);

int cnt = 1, ps[maxn], sz[maxn];



int find(int x){

    if (x == ps[x]) return x;

    return ps[x] = find(ps[x]);

}



void uni(int a, int b){

    a = find(a);

    b = find(b);



    if (a == b) return;



    ps[a] = b;

    sz[b] += sz[a];

    cnt = max(cnt, sz[b]);

}



void init(){

    iota(ps, ps+maxn, 0);

    for (int i=0; i<maxn; i++) sz[i] = 1;

}



int main (){

    ios_base::sync_with_stdio(false);

    cin.tie(0);

    int n,m;

    cin >> n >> m;

    init();



    for (int i=0; i<m; i++){

        int a, b;

        cin >> a >> b;

        uni(--a, --b);

    }



    cout << cnt << endl;

    return 0;   

}

// Optimized solution to the same problem (faster):
#include <bits/stdc++.h>

#define ll long long

using namespace std;

const ll mod=1e9+7;

int f[200005]={0};

int sz[200005]={0};

int n,m;

int ans=1;

int get(int x)

{

	if(x==f[x])return x;

	return f[x]=get(f[x]);

}

void merge(int x,int y)

{

	int xx=get(x);

	int yy=get(y);

	if(xx!=yy){

		f[xx]=yy;

		sz[yy]+=sz[xx];

		ans=max(ans,sz[yy]);

	}

	

}

void init()

{

	for(int i=1;i<=n;i++){

		f[i]=i;

		sz[i]=1;

	}

}

int main(){

    cin>>n>>m;

    init();

    while(m--){

    	int x,y;

    	cin>>x>>y;

    	merge(x,y);

	}

	cout<<ans<<endl;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <iostream>

#include <set>

#include <vector>

#include <string>

#include <algorithm>

#include <cmath>

using namespace std;

using ll=long long;

#define rep(i,a,b) for(ll i=a;i<ll(b);i++)

#define repr(i,a,b) for(ll i=a;i>=ll(b);i--)

#define endl "\n"

#define ALL(x) x.begin(),x.end()

#define ALLR(x) x.rbegin(),x.rend()

#define INF 1e9

#define DEBUG(x) cout<<"debug: "<<x<<endl



vector<bool> seen(200001);

set<int> graph[200001];



int surch(const set<int> g){

    int succ = 0;

    for(auto x : g){

        if(seen[x]) continue;

        seen[x] = true;

        succ++;

        succ += surch(graph[x]);

    }

    return succ;

}



int n, m;

int main() {

    cin >> n >> m;



    rep(_, 0, m){

        int a, b; cin >> a >> b;

        a--;b--;

        graph[a].insert(b);

        graph[b].insert(a);

    }



    int ans = 1;

    rep(i, 0, n){

        if(seen[i]) continue;

        int tmp = surch(graph[i]);

        ans = max(ans, tmp);

    }



    cout << ans << endl;

    return 0;

}


// Optimized solution to the same problem (faster):
#include <iostream>

#include <vector>

using namespace std;

using ll=long long;

#define rep(i,a,b) for(ll i=a;i<ll(b);i++)

#define endl "\n"



struct UnionFind {

    // 自身が根: その集合の要素数に-1を掛けたもの

    // 自身が葉: 根のID

    // -> 根であれは負の数、葉であれば正の数

    vector<int> data;



    // 全てを根として初期化

    UnionFind(int size = 0) : data(size, -1) {}



    // 根の検索

    int root(int x) {

        if(data[x] < 0) return x;

        return x = root(data[x]); // 経路圧縮

    }



    // 集合の結合

    bool unite(int x, int y) {

        x = root(x); y = root(y);

        if(x == y) return false;



        // 要素数が小さい方を大きい方に結合する

        if(data[x] > data[y]) swap(x, y); // -data[x] > -data[y] となるようにしたい

        data[x] += data[y]; // 要素数の加算

        data[y] = x; // 集合の結合

        return true;

    }



    // 要素xと要素yが同じ集合に属しているか

    bool same(int x, int y) { return root(x) == root(y); }



    // 要素xが属している集合の大きさ(サイズ)

    int size(int x) { return -data[root(x)]; }

};





int n, m;

int main() {

    cin >> n >> m;



    UnionFind UF(n);



    rep(i, 0, m){

        int a, b; cin >> a >> b;

        a--;b--;

        UF.unite(a, b);

    }



    int ans = 0;

    rep(i, 0, n){

        ans = max(ans, UF.size(i));

    }



    cout << ans << endl;



    return 0;

}


// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

 

#define ll long long

#define X first

#define Y second

#define MP make_pair

 

using namespace std;



const int N = 3e5 + 123;

const ll mod = 1e9 + 7;             



int n, h, w;

pair<int, int> a[N];

ll f[N], dp[N];

vector<int> srt;



ll bin_pow(ll x, ll y){

	ll res = 1;

	while(y){

		if(y & 1ll)

			res = res * x % mod;

		x = x * x % mod;

		y >>= 1LL;

	}

	return res;

}



ll calc(ll x, ll y){

	if(x < 0 || y < 0) return 0;

	return f[x + y - 2] * bin_pow(f[x - 1], mod - 2) % mod * bin_pow(f[y - 1], mod - 2) % mod;	

}



int main () {

	ios::sync_with_stdio(0);

	cin.tie(0);

	cout.tie(0);	



	f[0] = 1;

	for(ll i = 1;i <= 300000;i++){

		f[i] = f[i - 1] * i % mod;

	}



	cin >> h >> w >> n;

	for(int i = 1;i <= n;i++){

		int x, y;

		cin >> x >> y;

		a[i] = MP(x, y);

	}

	a[++n] = MP(h, w);



	sort(a + 1, a + n + 1);

	for(int i = 1;i <= n;i++){

		ll all = calc(a[i].X, a[i].Y);

		for(int j = 1; j < i; j++){

			all = (all - (dp[j] * calc(a[i].X - a[j].X + 1, a[i].Y - a[j].Y + 1) % mod) + mod) % mod;

		}

		dp[i] = all;

	}

	cout << dp[n];

	return 0;

}


// Optimized solution to the same problem (faster):
#include<cstdio>

#include<iostream>

#include<algorithm>

using namespace std;

const int MAXN = 3010;

const int MAXH = 100010, MAXW = 100010;

const int MOD = 1000000007;

int h, w, n;

struct node{

	int x, y;

}a[MAXN];

int fac[MAXH+MAXW], inv[MAXH+MAXW], f[MAXN+1];

inline int mul(int a, int b){return 1ll*a*b%MOD;}

inline int add(int a, int b){return (a+=b)>=MOD?a-MOD:a;}

inline int sub(int a, int b){return (a-=b)<0?a+MOD:a;}

inline int pw(int x, int p){int res=1;for(;p;p>>=1,x=mul(x,x))if(p&1)res=mul(res,x);return res;}

inline int C(int n, int m){return mul(fac[n], mul(inv[m], inv[n-m]));}

inline void prepare()

{

	fac[0] = 1;

	for(int i=1;i<=h+w;i++)

		fac[i] = mul(fac[i-1], i);

	inv[h+w] = pw(fac[h+w], MOD-2);

	for(int i=h+w;i>=1;i--)

		inv[i-1] = mul(inv[i], i);

}

inline bool cmp(node p, node q){return p.x!=q.x?p.x<q.x:p.y<q.y;}

int main()

{

	scanf("%d%d%d",&h,&w,&n);

	for(int i=1;i<=n;i++)

		scanf("%d%d",&a[i].x,&a[i].y);

	a[++n].x = h; a[n].y = w;

	prepare();

	sort(a+1, a+n+1, cmp);

	for(int i=1;i<=n;i++)

	{

		f[i] = C(a[i].x+a[i].y-2, a[i].x-1);

		for(int j=1;j<i;j++)

			if(a[j].x<=a[i].x&&a[j].y<=a[i].y)

				f[i] = sub(f[i], mul(f[j], C(a[i].x+a[i].y-a[j].x-a[j].y, a[i].x-a[j].x)));

	}

	printf("%d\n",f[n]);

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

int main()

{

    int i,c=0,n,j,p=0;

    string a,b;

    cin>>a>>b;

    cout<<b+a<<endl;





    }


// Optimized solution to the same problem (faster):
#include <stdio.h>

#include <string.h>



int main()

{

	char S[255],T[255];

	scanf("%s%s",S,T);

	strcat(T,S);

	printf("%s",T);

	

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<bits/stdc++.h>

using namespace std;

int main()

{

    string a, b;

    cin>>a>>b;

    cout<<b+a;

}

// Optimized solution to the same problem (faster):
#include <stdio.h>

#include <string.h>



int main()

{

	char S[255],T[255];

	scanf("%s%s",S,T);

	strcat(T,S);

	printf("%s",T);

	

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;

 

int main() {

    string a,b;

    cin>>a>>b;

    cout<<b+a<<endl;

}

// Optimized solution to the same problem (faster):
#include <stdio.h>

#include <string.h>



int main()

{

	char S[255],T[255];

	scanf("%s%s",S,T);

	strcat(T,S);

	printf("%s",T);

	

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include <bits/stdc++.h>

using namespace std;

int main()

{

    //freopen("input.txt", "r", stdin);

   // freopen("output.txt", "w", stdout);





    string a,b;



    cin >> a >> b;





    cout << b<<a;





    return 0;

}

// Optimized solution to the same problem (faster):
#include <stdio.h>

#include <string.h>



int main()

{

	char S[255],T[255];

	scanf("%s%s",S,T);

	strcat(T,S);

	printf("%s",T);

	

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<iostream>

using namespace std;

int main()

{

          string a,b;

          cin>>a>>b;

          cout<<b<<a<<endl;

return 0;

}


// Optimized solution to the same problem (faster):
#include <stdio.h>

#include <string.h>



int main()

{

	char S[255],T[255];

	scanf("%s%s",S,T);

	strcat(T,S);

	printf("%s",T);

	

	return 0;

}

// Fastest known solution for this problem:
// Original C++ solution (slower):
#include<iostream>

#include<string.h>

using namespace std;

int main()

{

    string s,t,x;

    cin>>s>>t;

    x=t+s;

    cout<<x<<endl;



    return 0;

}


// Optimized solution to the same problem (faster):
#include <stdio.h>

#include <string.h>



int main()

{

	char S[255],T[255];

	scanf("%s%s",S,T);

	strcat(T,S);

	printf("%s",T);

	

	return 0;

}

// Fastest known solution for this problem: