#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#define next fuck
#define FOR(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
#define MAXN (1000000*3)
int head[MAXN],next[MAXN],e[MAXN],deg[MAXN],cts=1;
void buildside(int a,int b){
	e[cts]=b;
	next[cts]=head[a];
	head[a]=cts++;
	deg[a]++;
}
struct node{
	int cur,ss;
	node(int cur=0,int ss=0):cur(cur),ss(ss)	{}
};
bool operator < (const node& a,const node& b){
	return ((double)a.cur/deg[a.ss])>((double)b.cur/deg[b.ss]);
}
priority_queue <node> q;
int cur[MAXN],save[MAXN],a[MAXN];
bool done[MAXN];
int k;
double gao(int n){
	double maxans=0.0;
	FOR(i,1,n)	q.push(node(cur[i],i));
//	cout<<q.top().ss<<endl;
	while (!q.empty()){
		node now=q.top();q.pop();
	//	cout<<"r "<<now.ss<<" "<<now.cur<<" "<<deg[now.ss]<<" "<<(double)now.cur/deg[now.ss]<<endl;
		if (done[now.ss])	continue;
		maxans=max(maxans,(double)now.cur/deg[now.ss]);
		done[now.ss]=true;
		for(int i=head[now.ss];i>0;i=next[i]){
			cur[e[i]]--;
			q.push(node(cur[e[i]],e[i]));
		}
	}
	return maxans;
}
void re_gao(double ans,int n){
	while (!q.empty())	q.pop();
	FOR(i,1,n)	cur[i]=save[i];
	FOR(i,1,n)	q.push(node(cur[i],i));
	memset(done,false,sizeof done);
	FOR(i,1,k)	done[a[i]]=true;
	int nowr=n;
	while (!q.empty()){
		node now=q.top();q.pop();
		if (done[now.ss])	continue;
//		cout<<(double)now.cur/deg[now.ss]<<endl;
		if ((double)now.cur/deg[now.ss]==ans){
		//	cout<<nowr-k<<endl;
			int temp=0;
			FOR(i,1,n)	if (!done[i])	temp++;//cout<<i<<" ";cout<<endl;
			cout<<temp<<endl;
			FOR(i,1,n)	if (!done[i])	cout<<i<<" ";cout<<endl;
			exit(0);
		}
		done[now.ss]=true;nowr--;
		for(int i=head[now.ss];i>0;i=next[i]){
			cur[e[i]]--;
			q.push(node(cur[e[i]],e[i]));
		}
	}
}
int main (int argc, char *argv[])
{
	std::ios::sync_with_stdio(false);
	int n,m;
	cin>>n>>m>>k;
	FOR(i,1,k)	cin>>a[i];
	FOR(i,1,m){
		int a,b;
		cin>>a>>b;
		buildside(a,b);
		buildside(b,a);
	}
	FOR(i,1,n)	cur[i]=deg[i];
	FOR(i,1,k){
		for(int j=head[a[i]];j>0;j=next[j]){
			cur[e[j]]--;
			cur[a[i]]--;
		}
		done[a[i]]=true;
	}
//	FOR(i,1,n)	cout<<cur[i]<<" ";cout<<endl;
	FOR(i,1,n)	save[i]=cur[i];
	double ans=gao(n);
//	cout<<ans<<endl;
	re_gao(ans,n);
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <queue>
#define next fuck
#define FOR(i,j,k) for(int i=j;i<=k;i++)
using namespace std;
#define MAXN (1000000*3)
int head[MAXN],next[MAXN],e[MAXN],deg[MAXN],cts=1;
void buildside(int a,int b){
	e[cts]=b;
	next[cts]=head[a];
	head[a]=cts++;
	deg[a]++;
}
struct node{
	int cur,ss;
	node(int cur=0,int ss=0):cur(cur),ss(ss)	{}
};
bool operator < (const node& a,const node& b){
	return ((double)a.cur/deg[a.ss])>((double)b.cur/deg[b.ss]);
}
priority_queue <node> q;
int cur[MAXN],save[MAXN],a[MAXN];
bool done[MAXN];
int k;
double gao(int n){
	double maxans=0.0;
	FOR(i,1,n)	q.push(node(cur[i],i));
//	cout<<q.top().ss<<endl;
	while (!q.empty()){
		node now=q.top();q.pop();
	//	cout<<"r "<<now.ss<<" "<<now.cur<<" "<<deg[now.ss]<<" "<<(double)now.cur/deg[now.ss]<<endl;
		if (done[now.ss])	continue;
		maxans=max(maxans,(double)now.cur/deg[now.ss]);
		done[now.ss]=true;
		for(int i=head[now.ss];i>0;i=next[i]){
			cur[e[i]]--;
			q.push(node(cur[e[i]],e[i]));
		}
	}
	return maxans;
}
void re_gao(double ans,int n){
	while (!q.empty())	q.pop();
	FOR(i,1,n)	cur[i]=save[i];
	FOR(i,1,n)	q.push(node(cur[i],i));
	memset(done,false,sizeof done);
	FOR(i,1,k)	done[a[i]]=true;
	int nowr=n;
	while (!q.empty()){
		node now=q.top();q.pop();
		if (done[now.ss])	continue;
//		cout<<(double)now.cur/deg[now.ss]<<endl;
		if (fabs((double)now.cur/deg[now.ss]-ans)<1e-8){
		//	cout<<nowr-k<<endl;
			int temp=0;
			FOR(i,1,n)	if (!done[i])	temp++;//cout<<i<<" ";cout<<endl;
			cout<<temp<<endl;
			FOR(i,1,n)	if (!done[i])	cout<<i<<" ";cout<<endl;
			exit(0);
		}
		done[now.ss]=true;nowr--;
		for(int i=head[now.ss];i>0;i=next[i]){
			cur[e[i]]--;
			q.push(node(cur[e[i]],e[i]));
		}
	}
}
int main (int argc, char *argv[])
{
	std::ios::sync_with_stdio(false);
	int n,m;
	cin>>n>>m>>k;
	FOR(i,1,k)	cin>>a[i];
	FOR(i,1,m){
		int a,b;
		cin>>a>>b;
		buildside(a,b);
		buildside(b,a);
	}
	FOR(i,1,n)	cur[i]=deg[i];
	FOR(i,1,k){
		for(int j=head[a[i]];j>0;j=next[j]){
			cur[e[j]]--;
			cur[a[i]]--;
		}
		done[a[i]]=true;
	}
//	FOR(i,1,n)	cout<<cur[i]<<" ";cout<<endl;
	FOR(i,1,n)	save[i]=cur[i];
	double ans=gao(n);
//	cout<<ans<<endl;
	re_gao(ans,n);
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+9;
int n,m,num[MAX],k;
vector<int> g[MAX];
bool used[MAX],mark[MAX];
set<pair<int,int> > s;
bool check(double p,bool pr=false)
{
	memset(used,false,sizeof used);
	s.clear();
	for (int i=0;i<n;i++)
		if (!mark[i])
		{
			int o=0;
			for (auto u:g[i]) if (!mark[u]) o++;
			used[i]=true,num[i]=o-ceil(p*g[i].size()),s.insert({num[i],i});
		}
	while (s.size())
	{
		auto b=*s.begin();
		if (b.first>=0) break;
		s.erase(b);
		used[b.second]=false;
		for (auto u:g[b.second]) if (used[u]) s.erase({num[u],u}),num[u]--,s.insert({num[u],u});
	}
	if (pr)
	{
		cout<<s.size()<<'\n';
		for (auto i:s) cout<<i.second+1<<' ';
	}
	if (s.size()) return true;
	return false;
}
int main()
{
	cin>>n>>m>>k;
	for (int i=0,a;i<k;i++) cin>>a,mark[a-1]=true;
	for (int i=0,v,u;i<m;i++) cin>>v>>u,v--,u--,g[v].push_back(u),g[u].push_back(v);
	double l=0,r=1,now=clock();
	while (clock()-now<1.9*CLOCKS_PER_SEC) (check((l+r)/2.)?l:r)=(l+r)/2.;
	check(l,true);
}


#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+9;
int n,m,num[MAX],k;
vector<int> g[MAX];
bool used[MAX],mark[MAX];
set<pair<int,int> > s;
bool check(double p,bool pr=0)
{
	memset(used,false,sizeof used),s.clear();
	for (int i=0;i<n;i++)
		if (!mark[i])
		{
			int o=0;
			for (auto u:g[i]) if (!mark[u]) o++;
			used[i]=true,num[i]=o-ceil(p*g[i].size()),s.insert({num[i],i});
		}
	while (s.size())
	{
		auto b=*s.begin();
		if (b.first>=0) break;
		s.erase(b),used[b.second]=false;
		for (auto u:g[b.second]) if (used[u]) s.erase({num[u],u}),num[u]--,s.insert({num[u],u});
	}
	if (pr){cout<<s.size()<<'\n'; for (auto i:s) cout<<i.second+1<<' ';}
	return s.size();
}
int main()
{
	cin>>n>>m>>k;
	for (int i=0,a;i<k;i++) cin>>a,mark[a-1]=true;
	for (int i=0,v,u;i<m;i++) cin>>v>>u,v--,u--,g[v].push_back(u),g[u].push_back(v);
	double l=0,r=1,now=clock();
	while (clock()-now<1.5*CLOCKS_PER_SEC) (check((l+r)/2.)?l:r)=(l+r)/2.;
	check(l,true);
}


#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+9;
int n,m,num[MAX],k;
vector<int> g[MAX];
bool used[MAX],mark[MAX];
set<pair<int,int> > s;
bool check(double p,bool pr=false)
{
	for (int i=0;i<n;i++)
		if (!mark[i])
		{
			int o=0;
			for (auto u:g[i]) if (!mark[u]) o++;
			s.insert({o-ceil(p*g[i].size()),i}),used[i]=true,num[i]=o-ceil(p*g[i].size());
		}
	while (s.size())
	{
		auto b=*s.begin();
		if (b.first>=0) break;
		s.erase(b),used[b.second]=false;
		for (auto u:g[b.second]) if (used[u]) s.erase({num[u],u}),num[u]--,s.insert({num[u],u});
	}
	if (pr)
	{
		cout<<s.size()<<'\n';
		for (auto i:s) cout<<i.second+1<<' ';
	}
	if (s.size()) return true;
	return false;
}
int main()
{
	cin>>n>>m>>k;
	for (int i=0,a;i<k;i++) cin>>a,mark[a-1]=true;
	for (int i=0,v,u;i<m;i++) cin>>v>>u,v--,u--,g[v].push_back(u),g[u].push_back(v);
	double l=0,r=1;
	for (int i=0;i<800;i++) (check((l+r)/2.)?l:r)=(l+r)/2.;
	check(l,true);
}


#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+9;
int n,m,num[MAX],k;
vector<int> g[MAX];
bool used[MAX],mark[MAX];
set<pair<int,int> > s;
bool check(double p,bool pr=false)
{
	memset(used,false,sizeof used);
	s.clear();
	for (int i=0;i<n;i++)
		if (!mark[i])
		{
			int o=0;
			for (auto u:g[i]) if (!mark[u]) o++;
			used[i]=true,num[i]=o-ceil(p*g[i].size()),s.insert({num[i],i});
		}
	while (s.size())
	{
		auto b=*s.begin();
		if (b.first>=0) break;
		s.erase(b);
		used[b.second]=false;
		for (auto u:g[b.second]) if (used[u]) s.erase({num[u],u}),num[u]--,s.insert({num[u],u});
	}
	if (pr)
	{
		cout<<s.size()<<'\n';
		for (auto i:s) cout<<i.second+1<<' ';
	}
	if (s.size()) return true;
	return false;
}
int main()
{
	cin>>n>>m>>k;
	for (int i=0,a;i<k;i++) cin>>a,mark[a-1]=true;
	for (int i=0,v,u;i<m;i++) cin>>v>>u,v--,u--,g[v].push_back(u),g[u].push_back(v);
	double l=0,r=1,now=clock();
	while (clock()-now<1.5*CLOCKS_PER_SEC) (check((l+r)/2.)?l:r)=(l+r)/2.;
	check(l,true);
}


#include<bits/stdc++.h>
using namespace std;
const int MAX=1e5+9;
int n,m,num[MAX],k;
vector<int> g[MAX];
bool used[MAX],mark[MAX];
set<pair<int,int> > s;
bool check(double p,bool pr=false)
{
	memset(used,false,sizeof used);
	s.clear();
	for (int i=0;i<n;i++)
		if (!mark[i])
		{
			int o=0;
			for (auto u:g[i]) if (!mark[u]) o++;
			used[i]=true,num[i]=o-ceil(p*g[i].size()),s.insert({num[i],i});
		}
	while (s.size())
	{
		auto b=*s.begin();
		if (b.first>=0) break;
		s.erase(b);
		used[b.second]=false;
		for (auto u:g[b.second]) if (used[u]) s.erase({num[u],u}),num[u]--,s.insert({num[u],u});
	}
	if (pr)
	{
		cout<<s.size()<<'\n';
		for (auto i:s) cout<<i.second+1<<' ';
	}
	if (s.size()) return true;
	return false;
}
int main()
{
	cin>>n>>m>>k;
	for (int i=0,a;i<k;i++) cin>>a,mark[a-1]=true;
	for (int i=0,v,u;i<m;i++) cin>>v>>u,v--,u--,g[v].push_back(u),g[u].push_back(v);
	double l=0,r=1;
	for (int i=0;i<800;i++) (check((l+r)/2.)?l:r)=(l+r)/2.;
	check(l,true);
}


#pragma warning(disable:4786)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<string>
#include<sstream>
#include<bitset>
#define LL long long
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps=1e-6;
const int maxn = 1e5 + 5;
int black[maxn] , vis[maxn] ;
int n , m;
vector<int>G[maxn];
struct Node
{
    int x , y ;
    double rate;
}node[maxn] , temp[maxn];
vector<int>ans;
void dfs(int cur , double x)
{
    for(int i = 0 ; i < G[cur].size() ;i++){
        int nt = G[cur][i];
        if(black[nt] || vis[nt])       continue;
        ++temp[nt].x;
        temp[nt].rate = 1.00 * (temp[nt].y - temp[nt].x) / temp[nt].y;
        if(temp[nt].rate < x){
            vis[nt] = 1;
            dfs(nt , x);
        }
    }
}
bool ok(double x)
{
//    if(x > 0.6)
//        puts("");
    mem(vis , 0);
    for(int i = 1 ; i <= n; i++){
        temp[i] = node[i];
    }
    for(int i = 1 ; i <= n ; i++){
        if(black[i])        continue;
        if(temp[i].rate < x){
            vis[i] = 1;
            dfs(i , x);
        }
    }
    for(int i = 1 ; i <= n; i++){
        if(!black[i] && !vis[i])        return true;
    }
    return false;
}
void solve()
{
    double left = 0 , right = 1;
    for(int i = 0 ; i < 100 ; i++){
        double mid = 0.5 * (left + right);
        if(ok(mid)){
            ans.clear();
            for(int i = 1 ; i <= n ; ++i){
                if(!black[i] && !vis[i]){
                    ans.push_back(i);
                }
            }
            left = mid;
        }
        else{
            right = mid;
        }
    }
    //printf("%lf %lf" , left , right);
}
int main()
{
    int k , u , v , x , y;
    scanf("%d %d %d" , &n , &m , &k);
    for(int i = 1 ; i <= n ; i++){

    }
    for(int i = 0 ; i < k ; i++){
        scanf("%d" , &x);
        black[x] = 1;
    }
    for(int i = 0 ; i < m ; i++){
        scanf("%d %d" , &u , &v);
        G[u].push_back(v);
        G[v].push_back(u);
        ++node[u].y;        ++node[v].y;
        if(black[v])      ++node[u].x;
        if(black[u])      ++node[v].x;
    }
    for(int i = 1 ; i <= n ; i++){
        node[i].rate = 1.0 * (node[i].y - node[i].x) / node[i].y;
    }
    solve();
    int sz = ans.size();
    printf("%d\n" , sz);
    for(int i = 0 ; i < sz ; i++){
        printf("%d " , ans[i]);
    }
    puts("");
    return 0;
}


#pragma warning(disable:4786)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<string>
#include<sstream>
#include<bitset>
#define LL long long
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps=1e-10;
const int maxn = 1e5 + 5;
int black[maxn] , vis[maxn] ;
int n , m;
vector<int>G[maxn];
struct Node
{
    int x , y ;
    double rate;
}node[maxn] , temp[maxn];
vector<int>ans;
void dfs(int cur , double x)
{
    for(int i = 0 ; i < G[cur].size() ;i++){
        int nt = G[cur][i];
        if(black[nt] || vis[nt])       continue;
        ++temp[nt].x;
        temp[nt].rate = 1.00 * (temp[nt].y - temp[nt].x) / temp[nt].y;
        if(temp[nt].rate < x && fabs(temp[nt].rate - x) > eps){
            vis[nt] = 1;
            dfs(nt , x);
        }
    }
}
bool ok(double x)
{
    mem(vis , 0);
    for(int i = 1 ; i <= n; i++){
        temp[i] = node[i];
    }
    for(int i = 1 ; i <= n ; i++){
        if(vis[i] || black[i])        continue;
        if(temp[i].rate < x && fabs(temp[i].rate - x) > eps){
            vis[i] = 1;
            dfs(i , x);
        }
    }
    for(int i = 1 ; i <= n; i++){
        if(!black[i] && !vis[i])        return true;
    }
    return false;
}
void solve()
{
    double left = 0 , right = 1;
    for(int i = 0 ; i < 100 ; i++){
        double mid = 0.5 * (left + right);
        if(ok(mid)){
            ans.clear();
            for(int i = 1 ; i <= n ; ++i){
                if(!black[i] && !vis[i]){
                    ans.push_back(i);
                }
            }
            left = mid;
        }
        else{
            right = mid;
        }
    }
}
int main()
{
    int k , u , v;
    scanf("%d %d %d" , &n , &m , &k);
    for(int i = 0 ; i < k ; i++){
        scanf("%d" , &u);
        black[u] = 1;
    }
    for(int i = 0 ; i < m ; i++){
        scanf("%d %d" , &u , &v);
        G[u].push_back(v);
        G[v].push_back(u);
        ++node[u].y;        ++node[v].y;
        if(black[v])      ++node[u].x;
        if(black[u])      ++node[v].x;
    }
    for(int i = 1 ; i <= n ; i++){
        node[i].rate = 1.00 * (node[i].y - node[i].x) / node[i].y;
    }
    solve();
    int sz = ans.size();
    if(sz){
        printf("%d\n" , sz);
        for(int i = 0 ; i < sz ; i++){
            printf("%d " , ans[i]);
        }
        puts("");
    }
    else{
        puts("1");
        int ans = -1;
        for(int i = 1 ; i <= n ; i++){
            if(!black[i]){
                ans = i;    break;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


#pragma warning(disable:4786)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<string>
#include<sstream>
#include<bitset>
#define LL long long
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps=1e-10;
const int maxn = 1e5 + 5;
int black[maxn] , vis[maxn] ;
int n , m;
vector<int>G[maxn];
struct Node
{
    int x , y ;
    double rate;
}node[maxn] , temp[maxn];
vector<int>ans;
void dfs(int cur , double x)
{
    for(int i = 0 ; i < G[cur].size() ;i++){
        int nt = G[cur][i];
        if(black[nt] || vis[nt])       continue;
        ++temp[nt].x;
        temp[nt].rate = 1.00 * (temp[nt].y - temp[nt].x) / temp[nt].y;
        if(temp[nt].rate < x && fabs(temp[nt].rate - x) > eps){
            vis[nt] = 1;
            dfs(nt , x);
        }
    }
}
bool ok(double x)
{
    mem(vis , 0);
    for(int i = 1 ; i <= n; i++){
        temp[i] = node[i];
    }
    for(int i = 1 ; i <= n ; i++){
        if(vis[i] || black[i])        continue;
        if(temp[i].rate < x && fabs(temp[i].rate - x) > eps){
            vis[i] = 1;
            dfs(i , x);
        }
    }
    for(int i = 1 ; i <= n; i++){
        if(!black[i] && !vis[i])        return true;
    }
    return false;
}
void solve()
{
    double left = 0 , right = 1;
    for(int i = 0 ; i < 100 ; i++){
        double mid = 0.5 * (left + right);
        if(ok(mid)){
            ans.clear();
            for(int i = 1 ; i <= n ; ++i){
                if(!black[i] && !vis[i]){
                    ans.push_back(i);
                }
            }
            left = mid;
        }
        else{
            right = mid;
        }
    }
}
int main()
{
    int k , u , v;
    scanf("%d %d %d" , &n , &m , &k);
    for(int i = 0 ; i < k ; i++){
        scanf("%d" , &x);
        black[x] = 1;
    }
    for(int i = 0 ; i < m ; i++){
        scanf("%d %d" , &u , &v);
        G[u].push_back(v);
        G[v].push_back(u);
        ++node[u].y;        ++node[v].y;
        if(black[v])      ++node[u].x;
        if(black[u])      ++node[v].x;
    }
    for(int i = 1 ; i <= n ; i++){
        node[i].rate = 1.00 * (node[i].y - node[i].x) / node[i].y;
    }
    solve();
    int sz = ans.size();
    if(sz){
        printf("%d\n" , sz);
        for(int i = 0 ; i < sz ; i++){
            printf("%d " , ans[i]);
        }
        puts("");
    }
    else{
        puts("1");
        int ans = -1;
        for(int i = 1 ; i <= n ; i++){
            if(!black[i]){
                ans = i;    break;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


#pragma warning(disable:4786)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<string>
#include<sstream>
#include<bitset>
#define LL long long
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps=1e-6;
const int maxn = 1e5 + 5;
int black[maxn] , vis[maxn] ;
int n , m;
vector<int>G[maxn];
struct Node
{
    int x , y ;
    double rate;
}node[maxn] , temp[maxn];
vector<int>ans;
void dfs(int cur , double x)
{
    for(int i = 0 ; i < G[cur].size() ;i++){
        int nt = G[cur][i];
        if(black[nt] || vis[nt])       continue;
        ++temp[nt].x;
        temp[nt].rate = 1.00 * (temp[nt].y - temp[nt].x) / temp[nt].y;
        if(temp[nt].rate < x){
            vis[nt] = 1;
            dfs(nt , x);
        }
    }
}
bool ok(double x)
{
//    if(x <0.5)
//        puts("");
    mem(vis , 0);
    for(int i = 1 ; i <= n; i++){
        temp[i] = node[i];
    }
    for(int i = 1 ; i <= n ; i++){
        if(black[i])        continue;
        if(temp[i].rate < x){
            vis[i] = 1;
            dfs(i , x);
        }
    }
    for(int i = 1 ; i <= n; i++){
        if(!black[i] && !vis[i])        return true;
    }
    return false;
}
void solve()
{
    double left = 0 , right = 1;
    for(int i = 0 ; i < 100 ; i++){
        double mid = 0.5 * (left + right);
        if(ok(mid)){
            ans.clear();
            for(int i = 1 ; i <= n ; ++i){
                if(!black[i] && !vis[i]){
                    ans.push_back(i);
                }
            }
            left = mid;
        }
        else{
            right = mid;
        }
    }
    //printf("%lf %lf" , left , right);
}
int main()
{
    int k , u , v , x , y;
    scanf("%d %d %d" , &n , &m , &k);
    for(int i = 1 ; i <= n ; i++){

    }
    for(int i = 0 ; i < k ; i++){
        scanf("%d" , &x);
        black[x] = 1;
    }
    for(int i = 0 ; i < m ; i++){
        scanf("%d %d" , &u , &v);
        G[u].push_back(v);
        G[v].push_back(u);
        ++node[u].y;        ++node[v].y;
        if(black[v])      ++node[u].x;
        if(black[u])      ++node[v].x;
    }
    for(int i = 1 ; i <= n ; i++){
        node[i].rate = 1.00 * (node[i].y - node[i].x) / node[i].y;
    }
    solve();
    int sz = ans.size();
    if(sz){
        printf("%d\n" , sz);
        for(int i = 0 ; i < sz ; i++){
            printf("%d " , ans[i]);
        }
        puts("");
    }
    else{
        puts("1");
        int ans = -1;
        for(int i = 1 ; i <= n ; i++){
            if(!black[i]){
                ans = i;    break;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


#pragma warning(disable:4786)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<string>
#include<sstream>
#include<bitset>
#define LL long long
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps=1e-10;
const int maxn = 1e5 + 5;
int black[maxn] , vis[maxn] ;
int n , m;
vector<int>G[maxn];
struct Node
{
    int x , y ;
    double rate;
}node[maxn] , temp[maxn];
vector<int>ans;
void dfs(int cur , double x)
{
    for(int i = 0 ; i < G[cur].size() ;i++){
        int nt = G[cur][i];
        if(black[nt] || vis[nt])       continue;
        ++temp[nt].x;
        temp[nt].rate = 1.00 * (temp[nt].y - temp[nt].x) / temp[nt].y;
        if(temp[nt].rate < x && fabs(temp[nt].rate - x) > eps){
            vis[nt] = 1;
            dfs(nt , x);
        }
    }
}
bool ok(double x)
{
//    if(x <0.5)
//        puts("");
    mem(vis , 0);
    for(int i = 1 ; i <= n; i++){
        temp[i] = node[i];
    }
    for(int i = 1 ; i <= n ; i++){
        if(black[i])        continue;
        if(temp[i].rate < x && fabs(temp[i].rate - x) > eps){
            vis[i] = 1;
            dfs(i , x);
        }
    }
    for(int i = 1 ; i <= n; i++){
        if(!black[i] && !vis[i])        return true;
    }
    return false;
}
void solve()
{
    double left = 0 , right = 1;
    for(int i = 0 ; i < 100 ; i++){
        double mid = 0.5 * (left + right);
        if(ok(mid)){
            ans.clear();
            for(int i = 1 ; i <= n ; ++i){
                if(!black[i] && !vis[i]){
                    ans.push_back(i);
                }
            }
            left = mid;
        }
        else{
            right = mid;
        }
    }
    //printf("%lf %lf" , left , right);
}
int main()
{
    int k , u , v , x , y;
    scanf("%d %d %d" , &n , &m , &k);
    for(int i = 1 ; i <= n ; i++){

    }
    for(int i = 0 ; i < k ; i++){
        scanf("%d" , &x);
        black[x] = 1;
    }
    for(int i = 0 ; i < m ; i++){
        scanf("%d %d" , &u , &v);
        G[u].push_back(v);
        G[v].push_back(u);
        ++node[u].y;        ++node[v].y;
        if(black[v])      ++node[u].x;
        if(black[u])      ++node[v].x;
    }
    for(int i = 1 ; i <= n ; i++){
        node[i].rate = 1.00 * (node[i].y - node[i].x) / node[i].y;
    }
    solve();
    int sz = ans.size();
    if(sz){
        printf("%d\n" , sz);
        for(int i = 0 ; i < sz ; i++){
            printf("%d " , ans[i]);
        }
        puts("");
    }
    else{
        puts("1");
        int ans = -1;
        for(int i = 1 ; i <= n ; i++){
            if(!black[i]){
                ans = i;    break;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


#pragma warning(disable:4786)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<string>
#include<sstream>
#include<bitset>
#define LL long long
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps=1e-10;
const int maxn = 1e5 + 5;
int black[maxn] , vis[maxn] ;
int n , m , flag;
vector<int>G[maxn];
struct Node
{
    int x , y ;
    double rate;
}node[maxn] , temp[maxn];
vector<int>ans;
void dfs(int cur , double x)
{
    for(int i = 0 ; i < G[cur].size() ;i++){
        int nt = G[cur][i];
        if(black[nt] || vis[nt])       continue;
        ++temp[nt].x;
        temp[nt].rate = 1.00 * (temp[nt].y - temp[nt].x) / temp[nt].y;
        if(temp[nt].rate < x && fabs(temp[nt].rate - x) > eps){
            vis[nt] = 1;
            dfs(nt , x);
        }
    }
}
bool ok(double x)
{
//    if(x <0.5)
//        puts("");
    mem(vis , 0);
    for(int i = 1 ; i <= n; i++){
        temp[i] = node[i];
    }
    for(int i = 1 ; i <= n ; i++){
        if(black[i])        continue;
        if(temp[i].rate < x && fabs(temp[i].rate - x) > eps){
            vis[i] = 1;
            dfs(i , x);
        }
    }
    for(int i = 1 ; i <= n; i++){
        if(!black[i] && !vis[i])        return true;
    }
    return false;
}
void solve()
{
    double left = 0 , right = 1;
    for(int i = 0 ; i < 100 ; i++){
        double mid = 0.5 * (left + right);
        if(ok(mid)){
            ans.clear();
            for(int i = 1 ; i <= n ; ++i){
                if(!black[i] && !vis[i]){
                    ans.push_back(i);
                }
            }
            left = mid;
        }
        else{
            right = mid;
        }
    }
    if(flag )
        printf("%lf %lf" , left , right);
}
int main()
{
    int k , u , v , x , y;
    scanf("%d %d %d" , &n , &m , &k);
    flag = 0;
    for(int i = 0 ; i < k ; i++){
        scanf("%d" , &x);
        if(i == 0 && x == 6554)     flag = 1;
        black[x] = 1;
    }
    for(int i = 0 ; i < m ; i++){
        scanf("%d %d" , &u , &v);
        G[u].push_back(v);
        G[v].push_back(u);
        ++node[u].y;        ++node[v].y;
        if(black[v])      ++node[u].x;
        if(black[u])      ++node[v].x;
    }
    for(int i = 1 ; i <= n ; i++){
        node[i].rate = 1.00 * (node[i].y - node[i].x) / node[i].y;
    }
    solve();
    int sz = ans.size();
    if(sz){
        printf("%d\n" , sz);
        for(int i = 0 ; i < sz ; i++){
            printf("%d " , ans[i]);
        }
        puts("");
    }
    else{
        puts("1");
        int ans = -1;
        for(int i = 1 ; i <= n ; i++){
            if(!black[i]){
                ans = i;    break;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}


#include <iostream>
#include <cstdio>
#include <set>
#include <vector>
#include <cassert>
using namespace std;

const int nmax = 1e5 + 10;

set<int> forts;
vector<int> g[nmax];
vector<bool> mark;
vector<pair<int, int> > frac;

bool cmp(const pair<int, int> &a, const pair<int, int> &b) {
    return (a.first * 1LL * b.second - a.second * 1LL * b.first < 0);
}

void dfs(const int u) {
    mark[u] = true;
    for(int i = 0; i < g[u].size(); ++i) {
        int v = g[u][i];
        if(not mark[v]) dfs(v);
        if(forts.count(v) == 0) frac[u].first++;
        frac[u].second++;
    }
}

void dfs_runner(int n) {
    mark.assign(n, false);
    frac.reserve(n);
    for(int i = 0; i < n; ++i) {
        if(not mark[i]) {
            dfs(i);
        }
    }
}

struct cmpii {
    bool operator()(const pair<pair<int, int>, int> &a, const pair<pair<int, int>, int> &b) const {
        return cmp(a.first, b.first);
    }
};

int main() {
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 0; i < k; ++i) {
        int x; scanf("%d", &x);
        x--;
        forts.insert(x);
    }
    for(int i = 0; i < m; ++i) {
        int a, b; scanf("%d%d", &a, &b);
        a--; b--;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    dfs_runner(n);

    multiset<pair<pair<int, int>, int>, cmpii> q;
    vector<pair<pair<int, int>, int> > possibles;
    for(int i = 0; i < n; ++i) {
        if(forts.count(i) == 0) {
            q.insert(make_pair(frac[i], i));
        } else {
            mark[i] = false;
        }
    }
    while(not q.empty()) {
        auto iii = *q.begin(); q.erase(q.begin());
        possibles.push_back(iii);
        int u = iii.second;
        mark[u] = false;

        for(int i = 0; i < g[u].size(); ++i) {
            int v = g[u][i];
            if(mark[v]) {
                q.erase(q.find(make_pair(frac[v], v)));
                assert(frac[v].first >= 1);
                frac[v].first--;
                q.insert(make_pair(frac[v], v));
            }
        }
    }

    int minidx = 0;
    for(int i = 0; i < possibles.size(); ++i) {
        auto kkk = possibles[minidx];
        auto iii = possibles[i];
        if(cmp(kkk.first, iii.first)) minidx = i;
    }
    printf("%d\n", (int)(possibles.size()) - minidx);
    for(int i = minidx; i < possibles.size(); ++i) {
        printf("%d ", possibles[i].second + 1);
    }
    return 0;
}


// I think that this should give AC, but there is some compiler problem
#include <iostream>
#include <set>
#include <vector>
#include <cassert>
using namespace std;

const int nmax = 1e5 + 10;

set<int> forts;
vector<int> g[nmax];
vector<bool> mark;
vector<pair<int, int> > frac;

bool cmp(const pair<int, int> &a, const pair<int, int> &b) {
    return (a.first * 1LL * b.second - a.second * 1LL * b.first < 0);
}

void dfs(const int u) {
    mark[u] = true;
    for(int i = 0; i < g[u].size(); ++i) {
        int v = g[u][i];
        if(not mark[v]) dfs(v);
        if(forts.count(v) == 0) frac[u].first++;
        frac[u].second++;
    }
}

void dfs_runner(int n) {
    mark.assign(n, false);
    frac.assign(n, {0, 0});
    for(int i = 0; i < n; ++i) {
        if(not mark[i]) {
            dfs(i);
        }
    }
}

struct cmpii {
    bool operator()(const pair<pair<int, int>, int> &a, const pair<pair<int, int>, int> &b) const {
        return cmp(a.first, b.first);
    }
};

int main() {
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 0; i < k; ++i) {
        int x; scanf("%d", &x);
        x--;
        forts.insert(x);
    }
    for(int i = 0; i < m; ++i) {
        int a, b; scanf("%d%d", &a, &b);
        a--; b--;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    dfs_runner(n);

    multiset<pair<pair<int, int>, int>, cmpii> q;
    vector<pair<pair<int, int>, int> > possibles;
    for(int i = 0; i < n; ++i) {
        if(forts.count(i) == 0) {
            q.insert(make_pair(frac[i], i));
        } else {
            mark[i] = false;
        }
    }
    while(not q.empty()) {
        auto iii = *q.begin(); q.erase(q.begin());
        possibles.push_back(iii);
        int u = iii.second;
        mark[u] = false;

        for(int i = 0; i < g[u].size(); ++i) {
            int v = g[u][i];
            if(mark[v]) {
                q.erase(q.find(make_pair(frac[v], v)));
                assert(frac[v].first >= 1);
                frac[v].first--;
                q.insert(make_pair(frac[v], v));
            }
        }
    }

    int minidx = 0;
    for(int i = 0; i < (int)possibles.size(); ++i) {
        auto kkk = possibles[minidx];
        auto iii = possibles[i];
        if(cmp(kkk.first, iii.first)) minidx = i;
    }
    printf("%d\n", (int)(possibles.size()) - minidx);
    for(int i = minidx; i < (int)possibles.size(); ++i) {
        printf("%d ", possibles[i].second + 1);
    }
    return 0;
}


#include <iostream>
#include <algorithm>
#include <vector>
#include <set>
#include <cassert>

#define pb push_back
#define mp make_pair

using namespace std;

bool cmp(const pair<int, int> &a, const pair<int, int> &b) {
    return ((a.first * 1LL * b.second - b.first * 1LL * a.second) < 0);
}

struct cmpiii {
    bool operator() (const pair<pair<int, int>, int> &a, const pair<pair<int, int>, int> &b) const {
        if(a.first.first * 1LL * b.first.second == b.first.first * a.first.second) {
            return (a.second < b.second);
        }
        else {
            return cmp(a.first, b.first);
        }
    }
};

const int nmax = 1e5 + 10;
vector<bool> fort;
vector<bool> mark;
vector<int> g[nmax];
vector<pair<int, int> > frac;
// (fraction), index
multiset<pair<pair<int, int>, int>, cmpiii> q;
vector<pair<pair<int, int>, int> > ans;

inline void dfs(const int u) {
    assert(mark[u] == false);
    mark[u] = true;
    int numer = 0;
    for(int i = 0; i < (int)g[u].size(); ++i) {
        int v = g[u][i];
        if(not fort[v]) numer++;
        if(not mark[v]) dfs(v);
    }
    frac[u] = mp(numer, (int)g[u].size());
}

void dfs_runner(const int n) {
    mark.assign(n, false);
    frac.assign(n, {0, 0});
    for(int i = 0; i < n; ++i) {
        if(not mark[i]) dfs(i);
    }
    for(int i = 0; i < n; ++i)
        assert(mark[i]);
}

int main() {
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);

    fort.assign(n, false);

    for(int i = 0; i < k; ++i) {
        int x; scanf("%d", &x);
        x--;
        fort[x] = true;
    }

    for(int i = 0; i < m; ++i) {
        int x, y;
        scanf("%d%d", &x, &y);
        x--, y--;
        g[x].pb(y);
        g[y].pb(x);
    }
    dfs_runner(n);

    for(int i = 0; i < n; ++i) {
        if(not fort[i]) {
            q.insert(mp(frac[i], i));
        }
    }

    while(not q.empty()) {
        ans.pb(*q.begin());
        int u = q.begin()->second;
        assert(q.begin()->first == frac[u]);
        assert(mark[u] == true);
        q.erase(q.begin());

        mark[u] = false;

        for(int i = 0; i < (int)g[u].size(); ++i) {
            int v = g[u][i];
            if(not fort[v] and mark[v]) {
                auto iii = *q.find(mp(frac[v], v));
                assert(iii.first == frac[v] and iii.second == v);
                q.erase(q.find(mp(frac[v], v)));
                frac[v].first--;
                q.insert(mp(frac[v], v));
            }
        }
    }

    int idx = 0;

    for(int i = 0; i < (int)ans.size(); ++i) {
        if(cmp(ans[idx].first, ans[i].first)) idx = i;
    }
    printf("%d\n", (int)ans.size() - idx);
    for(int i = idx; i < (int)ans.size(); ++i) {
        printf("%d ", ans[i].second + 1);
    }
    return 0;
}


#include <iostream>
#include <set>
#include <vector>
#include <cassert>
using namespace std;

const int nmax = 1e5 + 10;

set<int> forts;
vector<int> g[nmax];
vector<bool> mark;
vector<pair<int, int> > frac;

bool cmp(const pair<int, int> &a, const pair<int, int> &b) {
    return (a.first * 1LL * b.second - a.second * 1LL * b.first < 0);
}

void dfs(const int u) {
    mark[u] = true;
    for(int i = 0; i < g[u].size(); ++i) {
        int v = g[u][i];
        if(not mark[v]) dfs(v);
        if(forts.count(v) == 0) frac[u].first++;
        frac[u].second++;
    }
}

void dfs_runner(int n) {
    mark.assign(n, false);
    frac.reserve(n);
    for(int i = 0; i < n; ++i) {
        if(not mark[i]) {
            dfs(i);
        }
    }
}

struct cmpii {
    bool operator()(const pair<pair<int, int>, int> &a, const pair<pair<int, int>, int> &b) const {
        return cmp(a.first, b.first);
    }
};

int main() {
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    for(int i = 0; i < k; ++i) {
        int x; scanf("%d", &x);
        x--;
        forts.insert(x);
    }
    for(int i = 0; i < m; ++i) {
        int a, b; scanf("%d%d", &a, &b);
        a--; b--;
        g[a].push_back(b);
        g[b].push_back(a);
    }
    dfs_runner(n);

    multiset<pair<pair<int, int>, int>, cmpii> q;
    vector<pair<pair<int, int>, int> > possibles;
    for(int i = 0; i < n; ++i) {
        if(forts.count(i) == 0) {
            q.insert(make_pair(frac[i], i));
        } else {
            mark[i] = false;
        }
    }
    while(not q.empty()) {
        auto iii = *q.begin(); q.erase(q.begin());
        possibles.push_back(iii);
        int u = iii.second;
        mark[u] = false;

        for(int i = 0; i < g[u].size(); ++i) {
            int v = g[u][i];
            if(mark[v]) {
                q.erase(q.find(make_pair(frac[v], v)));
                assert(frac[v].first >= 1);
                frac[v].first--;
                q.insert(make_pair(frac[v], v));
            }
        }
    }

    int minidx = 0;
    for(int i = 0; i < possibles.size(); ++i) {
        auto kkk = possibles[minidx];
        auto iii = possibles[i];
        if(cmp(kkk.first, iii.first)) minidx = i;
    }
    printf("%d\n", (int)(possibles.size()) - minidx);
    for(int i = minidx; i < possibles.size(); ++i) {
        printf("%d ", possibles[i].second + 1);
    }
    return 0;
}


#include<bits/stdc++.h>

#define pb push_back
#define sz(a) ((int)a.size())
#define x first
#define y second
#define bpt(x) (__builtin_popcount(x))
#define bit(x, y) (((x)>>(y))&1)
#define bclz(x) (__builtin_clz(x))
#define bctz(x) (__builtin_ctz(x))
#define PQ priority_queue<pdi, vector<pdi>, greater<pdi> >
using namespace std;

typedef double DO;
typedef long long INT;
typedef pair<DO, int> pdi;
typedef vector<int> VI;

template<typename T, typename U> inline void smin(T &a, U b) {if(a>b) a=b;}
template<typename T, typename U> inline void smax(T &a, U b) {if(a<b) a=b;}

template<class T>inline void gn(T &x) {char c, sg=0; while (c=getchar(), (c>'9' || c<'0') && c!='-');for((c=='-'?sg=1, c=getchar():0), x=0; c>='0' && c<='9'; c=getchar()) x=(x<<1)+(x<<3)+c-'0';if (sg) x=-x;}
template<class T>inline void print(T x) {if (x<0) {putchar('-');return print(-x);}if (x<10) {putchar('0'+x);return;} print(x/10);putchar(x%10+'0');}
template <class T> inline void println(T x) {print(x); putchar('\n');}

int power(int a, int b, int m, int ans=1) {
	for(; b; b>>=1, a=1LL*a*a%m) if(b&1) ans=1LL*ans*a%m;
	return ans;
}

#define NN 100011
int n, m, k;
VI adj[NN];
int deg[NN];
int flag[NN];
int vst[NN];

PQ pq;
VI vec;
int ans;

int solve() {
	cin >> n >> m >> k;
	for(int i=1; i<=k; i++) {
		int u; gn(u);
		flag[u]= 1;
	}
	for(int i=0; i<m; i++) {
		int u, v; gn(u); gn(v);
		adj[u].pb(v); adj[v].pb(u);
		if(flag[u]==0) deg[v]++;
		if(flag[v]==0) deg[u]++;
	}
	for(int i=1; i<=n; i++) if(flag[i] == 0) {
		pq.push(pdi(1.0*deg[i] / sz(adj[i]), i));
	}
	DO mx=0;
	int ans, c=0;

	while(!pq.empty()) {
		pdi tmp = pq.top(); pq.pop();
		if(vst[tmp.y]) continue;
		vec.pb(tmp.y);
		vst[tmp.y] = 1;
		if(tmp.x > mx) {
			mx = tmp.x;
			ans=c;
		}
		c++;
		for(int &v : adj[tmp.y]) if(flag[v]==0) {
			deg[v]--;
			pq.push(pdi(1.0*deg[v] / sz(adj[v]), v));
		}
	}
	reverse(vec.begin(), vec.end());
	vec.resize(sz(vec)-ans);
	println(sz(vec));
	for(int &u : vec) println(u);

}

int main() {
#ifndef	ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif
	solve();
	return 0;
}


#include<bits/stdc++.h>

#define pb push_back
#define sz(a) ((int)a.size())
#define x first
#define y second
#define bpt(x) (__builtin_popcount(x))
#define bit(x, y) (((x)>>(y))&1)
#define bclz(x) (__builtin_clz(x))
#define bctz(x) (__builtin_ctz(x))
#define PQ priority_queue<pdi, vector<pdi>, greater<pdi> >
using namespace std;

typedef double DO;
typedef long long INT;
typedef pair<DO, int> pdi;
typedef vector<int> VI;

template<typename T, typename U> inline void smin(T &a, U b) {if(a>b) a=b;}
template<typename T, typename U> inline void smax(T &a, U b) {if(a<b) a=b;}

template<class T>inline void gn(T &x) {char c, sg=0; while (c=getchar(), (c>'9' || c<'0') && c!='-');for((c=='-'?sg=1, c=getchar():0), x=0; c>='0' && c<='9'; c=getchar()) x=(x<<1)+(x<<3)+c-'0';if (sg) x=-x;}
template<class T>inline void print(T x) {if (x<0) {putchar('-');return print(-x);}if (x<10) {putchar('0'+x);return;} print(x/10);putchar(x%10+'0');}
template <class T> inline void println(T x) {print(x); putchar('\n');}

int power(int a, int b, int m, int ans=1) {
	for(; b; b>>=1, a=1LL*a*a%m) if(b&1) ans=1LL*ans*a%m;
	return ans;
}

#define NN 100011
int n, m, k;
VI adj[NN];
int deg[NN];
int flag[NN];
int vst[NN];

PQ pq;
VI vec;
int ans;

int solve() {
	cin >> n >> m >> k;
	for(int i=1; i<=k; i++) {
		int u; gn(u);
		flag[u]= 1;
	}
	for(int i=0; i<m; i++) {
		int u, v; gn(u); gn(v);
		adj[u].pb(v); adj[v].pb(u);
		if(flag[u]==0) deg[v]++;
		if(flag[v]==0) deg[u]++;
	}
	for(int i=1; i<=n; i++) if(flag[i] == 0) {
		pq.push(pdi(1.0*deg[i] / sz(adj[i]), i));
	}
	DO mx=0;
	int ans=0, c=0;

	while(!pq.empty()) {
		pdi tmp = pq.top(); pq.pop();
		if(vst[tmp.y]) continue;
		vec.pb(tmp.y);
		vst[tmp.y] = 1;
		if(tmp.x > mx) {
			mx = tmp.x;
			ans = c;
		}
		c++;
		for(int &v : adj[tmp.y]) if(flag[v]==0) {
			deg[v]--;
			pq.push(pdi(1.0*deg[v] / sz(adj[v]), v));
		}
	}
	reverse(vec.begin(), vec.end());
	vec.resize(sz(vec)-ans);
	println(sz(vec));
	for(int u : vec) println(u);
}

int main() {
#ifndef	ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif
	solve();
	return 0;
}


#include<bits/stdc++.h>

#define x first
#define y second
#define pb push_back

using namespace std;

typedef long long INT;
typedef vector<int> VI;
typedef pair<int, int> pii;

template<typename T, typename U> inline void smin(T &a, const U &b) {if(a>b) a=b;}
template<typename T, typename U> inline void smax(T &a, const U &b) {if(a<b) a=b;}

template <class T> inline void gn(T &x) {char c, sg=0; while(c=getchar(), (c>'9' || c<'0') && c!='-'); for((c=='-' ? sg=1, c=getchar() : 0), x=0; c>='0' && c<='9'; c=getchar()) x=(x<<1)+(x<<3)+c-'0'; if(sg) x=-x;}
template <class T1, class T2> inline void gn(T1 &x1, T2 &x2) {gn(x1), gn(x2);}
int power(int a, int b, int m, int ans=1){for (; b; b>>=1, a=1LL*a*a%m) if (b&1) ans=1LL*ans*a%m; return ans;}

#define NN 100100
int deg[NN], vst[NN];
set <int> adj[NN];
int main(){
#ifndef ONLINE_JUDGE
	freopen("in.in", "r", stdin);
	freopen("out.out", "w", stdout);
#endif

	int n, m, k;
	cin >> n >> m >> k;
	for(int i=0; i<k; i++){
		int u; gn(u); vst[u]=1;
	}

	for(int i=0; i<m; i++){
		int u, v; gn(u, v);
		deg[u]++;
		deg[v]++;
		if(!vst[u] && !vst[v]) adj[u].insert(v), adj[v].insert(u);
	}

	typedef double DO;
	set <pair <DO, int> > s;
	for(int i=1; i<=n; i++) if(!vst[i]) s.insert(make_pair((DO)adj[i].size()/deg[i], i));

	DO ans=-1;
	int pos;
	VI vec;

	while(!s.empty()){
		auto p=*s.begin();
		s.erase(s.begin());
		int u=p.y;
		if(ans<p.x){
			ans=p.x;
			pos=vec.size();
		}
		vec.pb(u);
		for(int v : adj[u]){
			s.erase(make_pair((DO)adj[v].size()/deg[v], v));
			adj[v].erase(u);
			s.insert(make_pair((DO)adj[v].size()/deg[v], v));
		}
	}

	printf("%d\n", (int)vec.size()-pos);
	for(int i=pos; i<vec.size(); i++) printf("%d ", vec[i]);

	return 0;
}


#include <iostream>
#include <cstdio>
#include<list>
#include<iomanip>
#include<cmath>
#include<iostream>
#include<set>
#include<utility>
#include<memory.h>
#include<string>
#include <unordered_map>
#include<vector>
#include<queue>
#include <functional>
#include<stdio.h>
#include<assert.h>
#include<stack>
#include<sstream>
#include <cstdlib>
#include<map>
#include<algorithm>
#include<numeric>
using namespace std;
#define ll long long
#define sz(v)               ((int)((v).size()))
#define REP(i, v)       for(int i=0;i<sz(v);i++)
#define pb push_back
const int maxn = 100*1005;
bool bad[maxn];
vector<int> blocked;
vector<int> g[maxn];
bool seen[maxn];
int deg[maxn];
vector<int> good;
int n,m,k;
bool can(double mid)
{
	memset(bad,0,sizeof(bad));
	memset(deg,0,sizeof(deg));
	memset(seen,0,sizeof(seen));
	queue<int> q;
	for(int i = 0 ; i < n ; ++i) deg[i] = sz(g[i]);
	REP(i,blocked) q.push(blocked[i]);
	while(!q.empty())
	{
		int u = q.front(); q.pop();
		if(seen[u])
			continue;
		seen[u] = 1;
		REP(i,g[u])
		{
			int v = g[u][i];
			if(bad[v])
				continue;
			deg[v]--;
			if(double(deg[v] / (1.0*sz(g[v]))) < mid)
				q.push(v);
		}
	}
	good.clear();
	for(int i = 0 ; i < n ; ++i) if(!seen[i]) good.push_back(i);
	return sz(good) > 0;
}

int main()
{

	int u,v;
	scanf("%d %d %d",&n,&m,&k);
	for(int i = 0 ;i  < k ; ++i) scanf("%d",&u), --u,blocked.pb(u);
	for(int i = 0 ; i < m ; ++i)
		scanf("%d %d",&u,&v),--u,--v,g[u].pb(v),g[v].pb(u);

	double l = 0, r = 1.0;
	double ans = 0.0;

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

		double mid = (l + r) / 2.0;
		if(can(mid))
			l = mid,ans = mid;
		else r = mid;

	}
	can(ans);
	assert(sz(good) <= n - k);
	assert(sz(good) != 0);
	printf("%d\n",sz(good));
	REP(i,good) printf("%d ",good[i] + 1);

	return 0;

}


#include <iostream>
#include <cstdio>
#include<list>
#include<iomanip>
#include<cmath>
#include<iostream>
#include<set>
#include<utility>
#include<memory.h>
#include<string>
#include <unordered_map>
#include<vector>
#include<queue>
#include <functional>
#include<stdio.h>
#include<assert.h>
#include<stack>
#include<sstream>
#include <cstdlib>
#include<map>
#include<algorithm>
#include<numeric>
using namespace std;
#define ll long long
#define sz(v)               ((int)((v).size()))
#define REP(i, v)       for(int i=0;i<sz(v);i++)
#define pb push_back
const int maxn = 100*1005;
bool bad[maxn];
vector<int> blocked;
vector<int> g[maxn];
bool seen[maxn];
int deg[maxn];
vector<int> good;
int n,m,k;
bool can(double mid)
{
	memset(bad,0,sizeof(bad));
	memset(deg,0,sizeof(deg));
	memset(seen,0,sizeof(seen));
	queue<int> q;
	for(int i = 0 ; i < n ; ++i) deg[i] = sz(g[i]);
	REP(i,blocked) q.push(blocked[i]);
	while(!q.empty())
	{
		int u = q.front(); q.pop();
		if(seen[u])
			continue;
		seen[u] = 1;
		REP(i,g[u])
		{
			int v = g[u][i];
			if(bad[v])
				continue;
			deg[v]--;
			if(double(deg[v] / (1.0*sz(g[v]))) < mid)
				q.push(v);
		}
	}
	good.clear();
	for(int i = 0 ; i < n ; ++i) if(!seen[i]) good.push_back(i);
	return sz(good) > 0;
}

int main()
{

	int u,v;
	scanf("%d %d %d",&n,&m,&k);
	for(int i = 0 ;i  < k ; ++i) scanf("%d",&u), --u,blocked.pb(u);
	for(int i = 0 ; i < m ; ++i)
		scanf("%d %d",&u,&v),--u,--v,g[u].pb(v),g[v].pb(u);

	double l = 0, r = 1.0;
	double ans = 0.0;

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

		double mid = (l + r) / 2.0;
		if(can(mid))
			l = mid,ans = mid;
		else r = mid;

	}
	can(ans);
	assert(sz(good) <= n - k);
	assert(sz(good) != 0);
	printf("%d\n",sz(good));
	REP(i,good) printf("%d ",good[i] + 1);

	return 0;

}


#include <iostream>
#include <cstdio>
#include<list>
#include<iomanip>
#include<cmath>
#include<iostream>
#include<set>
#include<utility>
#include<memory.h>
#include<string>
#include <unordered_map>
#include<vector>
#include<queue>
#include <functional>
#include<stdio.h>
#include<assert.h>
#include<stack>
#include<sstream>
#include <cstdlib>
#include<map>
#include<algorithm>
#include<numeric>
using namespace std;
#define ll long long
#define sz(v)               ((int)((v).size()))
#define REP(i, v)       for(int i=0;i<sz(v);i++)
#define pb push_back
const int maxn = 100*1005;
bool bad[maxn];
vector<int> blocked;
vector<int> g[maxn];
bool seen[maxn];
int deg[maxn];
vector<int> good;
int n,m,k;
bool can(double mid)
{
	memset(bad,0,sizeof(bad));
	memset(deg,0,sizeof(deg));
	memset(seen,0,sizeof(seen));
	queue<int> q;
	for(int i = 0 ; i < n ; ++i) deg[i] = sz(g[i]);
	REP(i,blocked) q.push(blocked[i]);
	while(!q.empty())
	{
		int u = q.front(); q.pop();
		if(seen[u])
			continue;
		seen[u] = 1;
		REP(i,g[u])
		{
			int v = g[u][i];
			if(bad[v])
				continue;
			deg[v]--;
			if(double(deg[v] / (1.0*sz(g[v]))) < mid)
				q.push(v);
		}
	}
	good.clear();
	for(int i = 0 ; i < n ; ++i) if(!seen[i]) good.push_back(i);
	return sz(good) > 0;
}

int main()
{

	int u,v;
	scanf("%d %d %d",&n,&m,&k);
	for(int i = 0 ;i  < k ; ++i) scanf("%d",&u), --u,blocked.pb(u);
	for(int i = 0 ; i < m ; ++i)
		scanf("%d %d",&u,&v),--u,--v,g[u].pb(v),g[v].pb(u);

	double l = 0, r = 1.0;
	double ans = 0.0;

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

		double mid = (l + r) / 2.0;
		if(can(mid))
			l = mid,ans = mid;
		else r = mid;

	}
	can(ans);
	assert(sz(good) <= n - k);
	assert(sz(good) != 0);
	printf("%d\n",sz(good));
	REP(i,good) printf("%d ",good[i] + 1);

	return 0;

}


#include <iostream>
#include <cstdio>
#include<list>
#include<iomanip>
#include<cmath>
#include<iostream>
#include<set>
#include<utility>
#include<memory.h>
#include<string>
#include <unordered_map>
#include<vector>
#include<queue>
#include <functional>
#include<stdio.h>
#include<assert.h>
#include<stack>
#include<sstream>
#include <cstdlib>
#include<map>
#include<algorithm>
#include<numeric>
using namespace std;
#define ll long long
#define sz(v)               ((int)((v).size()))
#define REP(i, v)       for(int i=0;i<sz(v);i++)
#define pb push_back
const int maxn = 100*1005;
bool bad[maxn];
vector<int> blocked;
vector<int> g[maxn];
bool seen[maxn];
int deg[maxn];
vector<int> good;
int n,m,k;
bool can(double mid)
{
	memset(bad,0,sizeof(bad));
	memset(deg,0,sizeof(deg));
	memset(seen,0,sizeof(seen));
	queue<int> q;
	for(int i = 0 ; i < n ; ++i) deg[i] = sz(g[i]);
	REP(i,blocked) q.push(blocked[i]);
	while(!q.empty())
	{
		int u = q.front(); q.pop();
		if(seen[u])
			continue;
		seen[u] = 1;
		REP(i,g[u])
		{
			int v = g[u][i];
			if(bad[v])
				continue;
			deg[v]--;
			if(double(deg[v] / (1.0*sz(g[v]))) < mid)
				q.push(v);
		}
	}
	good.clear();
	for(int i = 0 ; i < n ; ++i) if(!seen[i]) good.push_back(i);
	return sz(good) > 0;
}

int main()
{

	int u,v;
	scanf("%d %d %d",&n,&m,&k);
	for(int i = 0 ;i  < k ; ++i) scanf("%d",&u), --u,blocked.pb(u);
	for(int i = 0 ; i < m ; ++i)
		scanf("%d %d",&u,&v),--u,--v,g[u].pb(v),g[v].pb(u);

	double l = 0, r = 1.0;
	double ans = 0.0;

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

		double mid = (l + r) / 2.0;
		if(can(mid))
			l = mid,ans = mid;
		else r = mid;

	}
	can(ans);
	assert(sz(good) <= n - k);
	assert(sz(good) != 0);
	printf("%d\n",sz(good));
	REP(i,good) printf("%d ",good[i] + 1);

	return 0;

}


#include <iostream>
#include <cstdio>
#include<list>
#include<iomanip>
#include<cmath>
#include<iostream>
#include<set>
#include<utility>
#include<memory.h>
#include<string>
#include <unordered_map>
#include<vector>
#include<queue>
#include <functional>
#include<stdio.h>
#include<assert.h>
#include<stack>
#include<sstream>
#include <cstdlib>
#include<map>
#include<algorithm>
#include<numeric>
using namespace std;
#define ll long long
#define sz(v)               ((int)((v).size()))
#define REP(i, v)       for(int i=0;i<sz(v);i++)
#define pb push_back
const int maxn = 100*1005;
bool bad[maxn];
vector<int> blocked;
vector<int> g[maxn];
bool seen[maxn];
int deg[maxn];
vector<int> good;
int n,m,k;
bool can(double mid)
{
	memset(bad,0,sizeof(bad));
	memset(deg,0,sizeof(deg));
	memset(seen,0,sizeof(seen));
	queue<int> q;
	for(int i = 0 ; i < n ; ++i) deg[i] = sz(g[i]);
	REP(i,blocked) q.push(blocked[i]);
	while(!q.empty())
	{
		int u = q.front(); q.pop();
		if(seen[u])
			continue;
		seen[u] = 1;
		REP(i,g[u])
		{
			int v = g[u][i];
			if(bad[v])
				continue;
			deg[v]--;
			if(double(deg[v] / (1.0*sz(g[v]))) < mid)
				q.push(v);
		}
	}
	good.clear();
	for(int i = 0 ; i < n ; ++i) if(!seen[i]) good.push_back(i);
	return sz(good) > 0;
}

int main()
{

	int u,v;
	scanf("%d %d %d",&n,&m,&k);
	for(int i = 0 ;i  < k ; ++i) scanf("%d",&u), --u,blocked.pb(u);
	for(int i = 0 ; i < m ; ++i)
		scanf("%d %d",&u,&v),--u,--v,g[u].pb(v),g[v].pb(u);

	double l = 0, r = 1.0;
	double ans = 0.0;

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

		double mid = (l + r) / 2.0;
		if(can(mid))
			l = mid,ans = mid;
		else r = mid;

	}
	can(ans);
	assert(sz(good) <= n - k);
	assert(sz(good) != 0);
	printf("%d\n",sz(good));
	REP(i,good) printf("%d ",good[i] + 1);

	return 0;

}


#include <iostream>
#include <cstdio>
#include<list>
#include<iomanip>
#include<cmath>
#include<iostream>
#include<set>
#include<utility>
#include<memory.h>
#include<string>
#include <unordered_map>
#include<vector>
#include<queue>
#include <functional>
#include<stdio.h>
#include<assert.h>
#include<stack>
#include<sstream>
#include <cstdlib>
#include<map>
#include<algorithm>
#include<numeric>
using namespace std;
#define ll long long
#define sz(v)               ((int)((v).size()))
#define REP(i, v)       for(int i=0;i<sz(v);i++)
#define pb push_back
#define lol {ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);}
const int maxn = 100*1005;
bool bad[maxn];
vector<int> blocked;
vector<int> g[maxn];
bool seen[maxn];
int deg[maxn];
vector<int> good;
int n,m,k;
bool can(double mid)
{
	memset(bad,0,sizeof(bad));
	memset(deg,0,sizeof(deg));
	memset(seen,0,sizeof(seen));
	queue<int> q;
	for(int i = 0 ; i < n ; ++i) deg[i] = sz(g[i]);
	REP(i,blocked) q.push(blocked[i]);
	while(!q.empty())
	{
		int u = q.front(); q.pop();
		if(seen[u])
			continue;
		seen[u] = 1;
		REP(i,g[u])
		{
			int v = g[u][i];
			if(bad[v])
				continue;
			deg[v]--;
			if(double(deg[v] / (1.0*sz(g[v]))) < mid)
				q.push(v);
		}
	}
	good.clear();
	for(int i = 0 ; i < n ; ++i) if(!seen[i]) good.push_back(i);
	return sz(good) > 0;
}

int main()
{

	int u,v;
	scanf("%d %d %d",&n,&m,&k);
	for(int i = 0 ;i  < k ; ++i) scanf("%d",&u), --u,blocked.pb(u);
	for(int i = 0 ; i < m ; ++i)
		scanf("%d %d",&u,&v),--u,--v,g[u].pb(v),g[v].pb(u);

	double l = 0, r = 1.0;
	double ans = 0.0;

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

		double mid = (l + r) / 2.0;
		if(can(mid))
			l = mid,ans = mid;
		else r = mid;

	}
	can(ans);
	assert(sz(good) <= n - k);
	assert(sz(good) != 0);
	printf("%d\n",sz(good));
	REP(i,good) printf("%d ",good[i] + 1);

	return 0;

}


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>
#include <set>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
void preprocess();
int check(double mid);
void print();

double low,high,mid;
int t,u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&t);
	set_bad(t);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

preprocess(); // 统计每个顶点的信息

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(LE(low,high))
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

#include <vector>
#include <set>
typedef struct VERTEX
{
std::set<struct VERTEX*> adj;
int is_bad, in_g;
int deg; // 出度
int enemy; // 所连敌城数
int fri; // 当前所连友城数
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];

void add_edge(int u, int v)
{
vert[u].adj.insert(&vert[v]);
}
void set_bad(int v)
{
vert[v].is_bad=1;
}

void preprocess()
{
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(!v->is_bad)
		{
		v->deg = v->adj.size();
		for(std::set<VERTEX_PTR>::iterator adj=v->adj.begin(); adj!=v->adj.end(); adj++)
			if((*adj)->is_bad)
				v->enemy++;
		}
	}
}

#include <queue>
int in_g; // 保留的城市数...
std::queue<VERTEX_PTR> give_up; // 放弃的城市...
int check(double mid) // 检查是否保留一些城市使它们安全感大于等于mid
{
double safe_val(VERTEX_PTR v);

in_g=0;
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(v->is_bad)
		v->in_g=0;
	else
		{
		v->fri = v->deg - v->enemy;
		v->in_g=1;
		in_g++;
		}
	}

for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(v->in_g && safe_val(v) < mid) // 注意!只判断我方城市
		{
		give_up.push(v); // 被抛弃的城市
		v->in_g=0;
		in_g--;
		}
	}
while(!give_up.empty())
	{
	VERTEX_PTR u = give_up.front();
	give_up.pop();
	for(std::set<VERTEX_PTR>::iterator iter=u->adj.begin(); iter!=u->adj.end(); iter++)
		{
		VERTEX_PTR v = (*iter);
		if(v->in_g) // u被放弃,但v还在...
			{
			v->fri--;
			if(safe_val(v) < mid)
				{
				give_up.push(v); // v也被放弃
				v->in_g=0;
				in_g--;
				}
			}
		}
	}
return in_g > 0;
}

double safe_val(VERTEX_PTR v)
{
//if(v->fri == 0)
//	return 1e-8;
//else
	return (double)v->fri / (double)v->deg;
}

void print()
{
printf("%d\n",in_g);
for(int i=1; i<=n; i++)
	{
	if(vert[i].in_g)
		printf("%d ", i);
	}
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>
#include <set>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
void preprocess();
int check(double mid);
void print();

double low,high,mid;
int t,u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&t);
	set_bad(t);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

preprocess(); // 统计每个顶点的信息

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(LE(low,high))
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

#include <vector>
#include <set>
typedef struct VERTEX
{
std::set<struct VERTEX*> adj;
int is_bad, in_g;
int deg; // 出度
int enemy; // 所连敌城数
int fri; // 当前所连友城数
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];

void add_edge(int u, int v)
{
vert[u].adj.insert(&vert[v]);
}
void set_bad(int v)
{
vert[v].is_bad=1;
}

void preprocess()
{
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(!v->is_bad)
		{
		v->deg = v->adj.size();
		for(std::set<VERTEX_PTR>::iterator adj=v->adj.begin(); adj!=v->adj.end(); adj++)
			if((*adj)->is_bad)
				v->enemy++;
		}
	}
}

#include <queue>
int in_g; // 保留的城市数...
std::queue<VERTEX_PTR> give_up; // 放弃的城市...
int check(double mid) // 检查是否保留一些城市使它们安全感大于等于mid
{
double safe_val(VERTEX_PTR v);

in_g=0;
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(v->is_bad)
		v->in_g=0;
	else
		{
		v->fri = v->deg - v->enemy;
		v->in_g=1;
		in_g++;
		}
	}

for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(v->in_g && safe_val(v) < mid) // 注意!只判断我方城市
		{
		give_up.push(v); // 被抛弃的城市
		v->in_g=0;
		in_g--;
		}
	}
while(!give_up.empty())
	{
	VERTEX_PTR u = give_up.front();
	give_up.pop();
	for(std::set<VERTEX_PTR>::iterator iter=u->adj.begin(); iter!=u->adj.end(); iter++)
		{
		VERTEX_PTR v = (*iter);
		if(v->in_g) // u被放弃,但v还在...
			{
			v->fri--;
			if(safe_val(v) < mid)
				{
				give_up.push(v); // v也被放弃
				v->in_g=0;
				in_g--;
				}
			}
		}
	}
return in_g > 0;
}

double safe_val(VERTEX_PTR v)
{
if(v->fri == 0)
	return 1e-8;
else
	return (double)v->fri / (double)v->deg;
}

void print()
{
printf("%d\n",in_g);
for(int i=1; i<=n; i++)
	{
	if(vert[i].in_g)
		printf("%d ", i);
	}
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>
#include <math.h>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
void preprocess();
int check(double mid);
void print();

double low,high,mid;
int u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&v);
	set_bad(v);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

preprocess(); // 统计每个顶点的信息

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(fabs(high-low) > 1e-8)
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

#include <vector>
#include <set>
typedef struct VERTEX
{
std::set<struct VERTEX*> adj;
int index;
int is_bad;
int deg; // 出度
int enemy; // 敌城数
int fri; // 友城数
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];

void set_bad(int v)
{
vert[v].is_bad=1;
}
void add_edge(int u, int v)
{
vert[u].adj.insert(&vert[v]);
}

void preprocess()
{
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	v->index=i;
	if(!v->is_bad)
		{
		v->deg = v->adj.size();
		for(std::set<VERTEX_PTR>::iterator vptr=v->adj.begin(); vptr!=v->adj.end(); vptr++)
			if((*vptr)->is_bad)
				v->enemy++;
		}
	}
}

#include <queue>
int g[MAXN], gsize;
std::vector<int> ans;
std::queue<VERTEX_PTR> q;
int check(double mid) // 检查是否能找到一些城市使它们安全感大于等于mid,用类似bfs的方式
{
double safe_val(VERTEX_PTR v);
void give_up(VERTEX_PTR u);
int found;

gsize=0;
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(!v->is_bad)
		{
		v->fri = v->deg - v->enemy;
		g[i]=1;
		gsize++;
		}
	}

for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(g[i] && safe_val(v) < mid)
		{
		q.push(v);
		g[i]=0;
		gsize--;
		}
	}

while(!q.empty())
	{
	VERTEX_PTR u = q.front();
	q.pop();
	for(std::set<VERTEX_PTR>::iterator vptr = u->adj.begin(); vptr!=u->adj.end(); vptr++)
		{
		VERTEX_PTR v = *vptr;
		if(g[v->index])
			{
			v->fri--;
			if(safe_val(v) < mid)
				{
				q.push(v);
				g[v->index]=0;
				gsize--;
				}
			}
		}
	}

if(gsize > 0)
	{
	ans.clear();
	for(int i=1; i<=n; i++)
		if(g[i])ans.push_back(i);
	}
return(gsize > 0);
}

double safe_val(VERTEX_PTR v)
{
if(v->fri == 0)
	return 1e-8;
else
	return (double)v->fri / (double)v->deg;
}

void print()
{
printf("%d\n",ans.size());
for(int i=0; i<ans.size(); i++)
	{
	printf("%d ", ans[i]);
	}
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>
#include <math.h>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
void preprocess();
int check(double mid);
void print();

double low,high,mid;
int u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&v);
	set_bad(v);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

preprocess(); // 统计每个顶点的信息

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(fabs(high-low) > 1e-8)
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

#include <vector>
#include <set>
typedef struct VERTEX
{
std::set<struct VERTEX*> adj;
int index;
int is_bad;
int deg; // 出度
int enemy; // 敌城数
int fri; // 友城数
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];

void set_bad(int v)
{
vert[v].is_bad=1;
}
void add_edge(int u, int v)
{
vert[u].adj.insert(&vert[v]);
}

void preprocess()
{
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	v->index=i;
	if(!v->is_bad)
		{
		v->deg = v->adj.size();
		for(std::set<VERTEX_PTR>::iterator vptr=v->adj.begin(); vptr!=v->adj.end(); vptr++)
			if((*vptr)->is_bad)
				v->enemy++;
		}
	}
}

#include <queue>
std::set<VERTEX_PTR> g;
std::vector<VERTEX_PTR> remove_from_g; // 放弃的城市...
int check(double mid) // 检查是否能找到一些城市使它们安全感大于等于mid
{
double safe_val(VERTEX_PTR v);
void give_up(VERTEX_PTR u);
int found;

g.clear();
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(!v->is_bad)
		{
		v->fri = v->deg - v->enemy;
		g.insert(v);
		}
	}

while(g.size() > 0)
	{
	found=1;
	remove_from_g.clear();
	for(std::set<VERTEX_PTR>::iterator vptr = g.begin(); vptr!=g.end(); vptr++)
		{
		VERTEX_PTR v = (*vptr);
		if(safe_val(v) < mid)
			{
			give_up(v);
			found=0;
			}
		}
	if(found)
		return(1);
	for(int i=0; i<remove_from_g.size(); i++)
		g.erase(remove_from_g[i]);
	}
return(0);
}

void give_up(VERTEX_PTR u)
{
for(std::set<VERTEX_PTR>::iterator vptr=u->adj.begin(); vptr!=u->adj.end(); vptr++)
	{
	VERTEX_PTR v = (*vptr);
	if(g.count(v))
		v->fri--;
	}
remove_from_g.push_back(u);
}

double safe_val(VERTEX_PTR v)
{
//if(v->fri == 0)
//	return 1e-8;
//else
	return (double)v->fri / (double)v->deg;
}

void print()
{
printf("%d\n",g.size());
for(std::set<VERTEX_PTR>::iterator vptr = g.begin(); vptr!=g.end(); vptr++)
	{
	VERTEX_PTR v = *vptr;
	printf("%d ", v->index);
	}
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>
#include <set>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
void preprocess();
int check(double mid);
void print();

double low,high,mid;
int t,u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&t);
	set_bad(t);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

preprocess(); // 统计每个顶点的信息

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(LE(low,high))
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

#include <vector>
#include <set>
typedef struct VERTEX
{
std::set<struct VERTEX*> adj;
int index;
int is_bad;
int deg; // 出度
int enemy; // 所连敌城数
int fri; // 当前所连友城数
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];

void add_edge(int u, int v)
{
vert[u].adj.insert(&vert[v]);
}
void set_bad(int v)
{
vert[v].is_bad=1;
}

void preprocess()
{
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	v->index=i;
	if(!v->is_bad)
		{
		v->deg = v->adj.size();
		for(std::set<VERTEX_PTR>::iterator adj=v->adj.begin(); adj!=v->adj.end(); adj++)
			if((*adj)->is_bad)
				v->enemy++;
		}
	}
}

#include <queue>
std::set<VERTEX_PTR> g;
std::vector<VERTEX_PTR> remove_from_g; // 放弃的城市...
int check(double mid) // 检查是否能找到一些城市使它们安全感大于等于mid
{
double safe_val(VERTEX_PTR v);
void give_up(VERTEX_PTR u);
int found;

for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(!v->is_bad)
		{
		v->fri = v->deg - v->enemy;
		g.insert(&vert[i]);
		}
	}

while(!g.empty())
	{
	found=1;
	remove_from_g.clear();
	for(std::set<VERTEX_PTR>::iterator vptr = g.begin(); vptr!=g.end(); vptr++)
		{
		VERTEX_PTR v = (*vptr);
		if(safe_val(v) < mid)
			{
			give_up(v);
			found=0;
			}
		}
	if(found)
		break;
	for(int i=0; i<remove_from_g.size(); i++)
		g.erase(remove_from_g[i]);
	}
return g.size() > 0;
}

void give_up(VERTEX_PTR u)
{
for(std::set<VERTEX_PTR>::iterator vptr=u->adj.begin(); vptr!=u->adj.end(); vptr++)
	{
	VERTEX_PTR v = (*vptr);
	if(g.count(v))
		v->fri--;
	}
remove_from_g.push_back(u);
}

double safe_val(VERTEX_PTR v)
{
if(v->fri == 0)
	return 1e-8;
else
	return (double)v->fri / (double)v->deg;
}

void print()
{
printf("%d\n",g.size());
for(std::set<VERTEX_PTR>::iterator vptr = g.begin(); vptr!=g.end(); vptr++)
	{
	VERTEX_PTR v = *vptr;
	printf("%d ", v->index);
	}
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>
#include <math.h>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
void preprocess();
int check(double mid);
void print();

double low,high,mid;
int u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&v);
	set_bad(v);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

preprocess(); // 统计每个顶点的信息

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(fabs(high-low) > 1e-8)
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

#include <vector>
#include <set>
typedef struct VERTEX
{
std::set<struct VERTEX*> adj;
int index;
int is_bad;
int deg; // 出度
int enemy; // 敌城数
int fri; // 友城数
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];

void set_bad(int v)
{
vert[v].is_bad=1;
}
void add_edge(int u, int v)
{
vert[u].adj.insert(&vert[v]);
}

void preprocess()
{
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	v->index=i;
	if(!v->is_bad)
		{
		v->deg = v->adj.size();
		for(std::set<VERTEX_PTR>::iterator vptr=v->adj.begin(); vptr!=v->adj.end(); vptr++)
			if((*vptr)->is_bad)
				v->enemy++;
		}
	}
}

#include <queue>
int g[MAXN], gsize;
std::vector<int> ans;
std::queue<VERTEX_PTR> q;
int check(double mid) // 检查是否能找到一些城市使它们安全感大于等于mid,用类似bfs的方式
{
double safe_val(VERTEX_PTR v);
void give_up(VERTEX_PTR u);
int found;

gsize=0;
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(!v->is_bad)
		{
		v->fri = v->deg - v->enemy;
		g[i]=1;
		gsize++;
		}
	}

for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(g[i] && safe_val(v) < mid)
		{
		q.push(v);
		g[i]=0;
		gsize--;
		}
	}

while(!q.empty())
	{
	VERTEX_PTR u = q.front();
	q.pop();
	for(std::set<VERTEX_PTR>::iterator vptr = u->adj.begin(); vptr!=u->adj.end(); vptr++)
		{
		VERTEX_PTR v = *vptr;
		if(g[v->index])
			{
			v->fri--;
			if(safe_val(v) < mid)
				{
				q.push(v);
				g[v->index]=0;
				gsize--;
				}
			}
		}
	}
if(gsize > 0)
	{
	for(int i=1; i<=n; i++)
		if(g[i])ans.push_back(i);
	}
return(gsize > 0);
}

double safe_val(VERTEX_PTR v)
{
if(v->fri == 0)
	return 1e-8;
else
	return (double)v->fri / (double)v->deg;
}

void print()
{
printf("%d\n",ans.size());
for(int i=0; i<ans.size(); i++)
	{
	printf("%d ", ans[i]);
	}
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void add_edge(int u, int v);
int check(double mid);
int LE(double a, double b);
void print();
void preprocess();
void set_bad(int v);

double low,high,mid;
int t,u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&t);
	set_bad(t);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

preprocess();

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(LE(low,high))
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

#include <set>
typedef struct VERTEX
{
std::set<VERTEX*> adj;
int index;
int is_bad,deg,enemy,fri;
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];
void set_bad(int v)
{
vert[v].is_bad=1;
}
void add_edge(int u, int v)
{
vert[u].adj.insert(&vert[v]);
}

void preprocess()
{
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR u = &vert[i];
	u->index=i;
	//u->deg=u->adj.size();
	//for(std::set<VERTEX_PTR>::iterator vptr=u->adj.begin(); vptr!=u->adj.end(); vptr++)
	//	{
	//	VERTEX_PTR v = *vptr;
	//	if(v->is_bad)
	//		u->enemy++;
	//	}
	}
}

#include <queue>
using std::vector;

std::set<VERTEX_PTR> g;
std::set<VERTEX_PTR> gg;
int check(double mid) // 检查是否能删除一些点使活跃度大于等于mid
{
double safe_val(VERTEX_PTR u);
int satisfy;

g.clear();
for(int i=1; i<=n; i++)
	{
	if(!vert[i].is_bad)
		g.insert(&vert[i]);
	}
while(g.size() > 0)
	{
	satisfy=1;
	for(int i=1; i<=n; i++)
		{
		VERTEX_PTR v = &vert[i];
		if(g.count(v) && (safe_val(v) < mid))
			{
			g.erase(v);
			satisfy=0;
			}
		}
	if(satisfy)
		{
		gg=g;
		return(1);
		}
	}
return(0);
}

double safe_val(VERTEX_PTR u) // 求一个城市的安全感
{
int d, adj;
d = adj = 0;
for(std::set<VERTEX_PTR>::iterator vptr=u->adj.begin();vptr!=u->adj.end();vptr++)
	{
	VERTEX_PTR v = *vptr;
	if(g.count(v)) // 如果邻接点在S中...
		{
		d++;
		}
	adj++;
	}
if(d == 0)  // 比如只有两座城市,其中一座被敌人占领,那么另一座的安全感最大只能为0
			// 所以要返回一个近似0的值以包含这种情况
	return 1e-8;
else
	return 1.0 * d / adj;
}

void print()
{
printf("%d\n",gg.size());
for(std::set<VERTEX_PTR>::iterator vptr=gg.begin();vptr!=gg.end();vptr++)
	printf("%d ", (*vptr)->index);
}

#include <math.h>
int LE(double a, double b) // less equal
{
return fabs(a-b) > 1e-8;
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void add_edge(int u, int v);
int check(double mid);
int LE(double a, double b);
void print();
void preprocess();
void set_bad(int v);

double low,high,mid;
int t,u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&t);
	set_bad(t);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

preprocess();

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(LE(low,high))
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

#include <set>
typedef struct VERTEX
{
std::set<VERTEX*> adj;
int index;
int is_bad,deg,enemy,fri;
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];
void set_bad(int v)
{
vert[v].is_bad=1;
}
void add_edge(int u, int v)
{
vert[u].adj.insert(&vert[v]);
}

void preprocess()
{
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR u = &vert[i];
	u->index=i;
	//u->deg=u->adj.size();
	//for(std::set<VERTEX_PTR>::iterator vptr=u->adj.begin(); vptr!=u->adj.end(); vptr++)
	//	{
	//	VERTEX_PTR v = *vptr;
	//	if(v->is_bad)
	//		u->enemy++;
	//	}
	}
}

#include <queue>
using std::vector;

std::set<VERTEX_PTR> g;
int check(double mid) // 检查是否能删除一些点使活跃度大于等于mid
{
double safe_val(VERTEX_PTR u);
int satisfy;

for(int i=1; i<=n; i++)
	{
	if(!vert[i].is_bad)
		g.insert(&vert[i]);
	}
while(g.size() > 0)
	{
	satisfy=1;
	for(int i=1; i<=n; i++)
		{
		VERTEX_PTR v = &vert[i];
		if(g.count(v) && (safe_val(v) < mid))
			{
			g.erase(v);
			satisfy=0;
			}
		}
	if(satisfy)
		{
		return(1);
		}
	}
return(0);
}

double safe_val(VERTEX_PTR u) // 求一个城市的安全感
{
int d, adj;
d = adj = 0;
for(std::set<VERTEX_PTR>::iterator vptr=u->adj.begin();vptr!=u->adj.end();vptr++)
	{
	VERTEX_PTR v = *vptr;
	if(g.count(v)) // 如果邻接点在S中...
		{
		d++;
		}
	adj++;
	}
if(d == 0)  // 比如只有两座城市,其中一座被敌人占领,那么另一座的安全感最大只能为0
			// 所以要返回一个近似0的值以包含这种情况
	return 1e-8;
else
	return 1.0 * d / adj;
}

void print()
{
printf("%d\n",g.size());
for(std::set<VERTEX_PTR>::iterator vptr=g.begin();vptr!=g.end();vptr++)
	printf("%d ", (*vptr)->index);
}

#include <math.h>
int LE(double a, double b) // less equal
{
return fabs(a-b) > 1e-8;
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>
#include <math.h>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
void preprocess();
int check(double mid);
void print();

double low,high,mid;
int t,u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&t);
	set_bad(t);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

preprocess(); // 统计每个顶点的信息

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
while(fabs(high-low) > 1e-8)
//for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

#include <vector>
#include <set>
typedef struct VERTEX
{
std::set<struct VERTEX*> adj;
int index;
int is_bad;
int deg; // 出度
int enemy; // 所连敌城数
int fri; // 当前所连友城数
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];

void add_edge(int u, int v)
{
vert[u].adj.insert(&vert[v]);
}
void set_bad(int v)
{
vert[v].is_bad=1;
}

void preprocess()
{
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	v->index=i;
	if(!v->is_bad)
		{
		v->deg = v->adj.size();
		for(std::set<VERTEX_PTR>::iterator adj=v->adj.begin(); adj!=v->adj.end(); adj++)
			if((*adj)->is_bad)
				v->enemy++;
		}
	}
}

#include <queue>
std::set<VERTEX_PTR> g;
std::vector<VERTEX_PTR> remove_from_g; // 放弃的城市...
int check(double mid) // 检查是否能找到一些城市使它们安全感大于等于mid
{
double safe_val(VERTEX_PTR v);
void give_up(VERTEX_PTR u);
int found;

for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(!v->is_bad)
		{
		v->fri = v->deg - v->enemy;
		g.insert(&vert[i]);
		}
	}

while(!g.empty())
	{
	found=1;
	remove_from_g.clear();
	for(std::set<VERTEX_PTR>::iterator vptr = g.begin(); vptr!=g.end(); vptr++)
		{
		VERTEX_PTR v = (*vptr);
		if(safe_val(v) < mid)
			{
			give_up(v);
			found=0;
			}
		}
	if(found)
		break;
	for(int i=0; i<remove_from_g.size(); i++)
		g.erase(remove_from_g[i]);
	}
return g.size() > 0;
}

void give_up(VERTEX_PTR u)
{
for(std::set<VERTEX_PTR>::iterator vptr=u->adj.begin(); vptr!=u->adj.end(); vptr++)
	{
	VERTEX_PTR v = (*vptr);
	if(g.count(v))
		v->fri--;
	}
remove_from_g.push_back(u);
}

double safe_val(VERTEX_PTR v)
{
if(v->fri == 0)
	return 1e-8;
else
	return (double)v->fri / (double)v->deg;
}

void print()
{
printf("%d\n",g.size());
for(std::set<VERTEX_PTR>::iterator vptr = g.begin(); vptr!=g.end(); vptr++)
	{
	VERTEX_PTR v = *vptr;
	printf("%d ", v->index);
	}
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>
#include <set>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
int check(double mid);
void print();

double low,high,mid;
int t,u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&t);
	set_bad(t);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(LE(low,high))
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

#include <vector>
typedef struct EDGE
{
struct VERTEX* to;
}EDGE,*EDGE_PTR;
typedef struct VERTEX
{
std::vector<EDGE> edge;
int is_bad, in_g;
int deg; // 出度
int enemy; // 所连敌城数
int fri; // 当前所连友城数
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];

void add_edge(int u, int v)
{
EDGE e;
e.to=&vert[v];
vert[u].edge.push_back(e);
vert[u].deg++;
if(vert[v].is_bad)
	vert[u].enemy++;
}
void set_bad(int v)
{
vert[v].is_bad=1;
}

#include <queue>
int in_g; // 保留的城市数...
std::queue<VERTEX_PTR> give_up; // 放弃的城市...
int check(double mid) // 检查是否保留一些城市使它们安全感大于等于mid
{
double safe_val;

in_g=0;
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(v->is_bad)
		v->in_g=0;
	else
		{
		v->in_g=1;
		in_g++;
		}
	v->fri = v->deg - v->enemy;
	}

for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(v->fri == 0)
		safe_val=1e-8;
	else
		safe_val=v->fri / v->deg;
	if(safe_val < mid)
		{
		give_up.push(v); // 被抛弃的城市
		v->in_g=0;
		in_g--;
		}
	}
while(!give_up.empty())
	{
	VERTEX_PTR u = give_up.front();
	give_up.pop();
	for(int i=0; i<u->edge.size(); i++)
		{
		EDGE_PTR e = &u->edge[i];
		VERTEX_PTR v = e->to;
		if(v->in_g == 1) // u被放弃,但v还在...
			{
			v->fri--;
			if(v->fri / v->deg < mid)
				{
				give_up.push(v); // v也被放弃
				v->in_g=0;
				in_g--;
				}
			}
		}
	}
return in_g > 0;
}

void print()
{
printf("%d\n",in_g);
for(int i=1; i<=n; i++)
	{
	if(vert[i].in_g)
		printf("%d ", i);
	}
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>
#include <set>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
int check(double mid);
void print();

double low,high,mid;
int t,u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&t);
	set_bad(t);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(LE(low,high))
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

#include <vector>
typedef struct EDGE
{
struct VERTEX* to;
}EDGE,*EDGE_PTR;
typedef struct VERTEX
{
std::vector<EDGE> edge;
int is_bad, in_g;
int deg; // 出度
int enemy; // 所连敌城数
int fri; // 当前所连友城数
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];

void add_edge(int u, int v)
{
EDGE e;
e.to=&vert[v];
vert[u].edge.push_back(e);
vert[u].deg++;
if(vert[v].is_bad)
	vert[u].enemy++;
}
void set_bad(int v)
{
vert[v].is_bad=1;
}

#include <queue>
int in_g; // 保留的城市数...
std::queue<VERTEX_PTR> give_up; // 放弃的城市...
int check(double mid) // 检查是否保留一些城市使它们安全感大于等于mid
{
double safe_val(VERTEX_PTR v);

in_g=0;
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(v->is_bad)
		v->in_g=0;
	else
		{
		v->in_g=1;
		in_g++;
		}
	v->fri = v->deg - v->enemy;
	}

for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(v->in_g && safe_val(v) < mid) // 注意!只判断我方城市
		{
		give_up.push(v); // 被抛弃的城市
		v->in_g=0;
		in_g--;
		}
	}
while(!give_up.empty())
	{
	VERTEX_PTR u = give_up.front();
	give_up.pop();
	for(int i=0; i<u->edge.size(); i++)
		{
		EDGE_PTR e = &u->edge[i];
		VERTEX_PTR v = e->to;
		if(v->in_g) // u被放弃,但v还在...
			{
			v->fri--;
			if(safe_val(v) < mid)
				{
				give_up.push(v); // v也被放弃
				v->in_g=0;
				in_g--;
				}
			}
		}
	}
return in_g > 0;
}

double safe_val(VERTEX_PTR v)
{
if(v->fri == 0)
	return 1e-8;
else
	return (double)v->fri / (double)v->deg;
}

void print()
{
printf("%d\n",in_g);
for(int i=1; i<=n; i++)
	{
	if(vert[i].in_g)
		printf("%d ", i);
	}
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数
int bad[MAXN];
int ans,selected[MAXN];

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void add_edge(int u, int v);
int check(double mid ,int *pans, int *pselected);
int LE(double a, double b);

double low,high,mid;
int t,u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&t);
	bad[t]=1;
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(LE(low,high))
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid, &ans, selected))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

printf("%d\n",ans);
for(int i=1; i<=ans; i++)
	printf("%d ", selected[i]);

return 0;
}

typedef struct EDGE
{
int from,to,next;
}EDGE;

EDGE edge[2*MAXM];
int link_e[MAXN], etot;
void add_edge(int u, int v)
{
for(int i=link_e[u];i;i=edge[i].next)
	if(edge[i].to == v)
		return;
EDGE e;
e.from = u;
e.to = v;
e.next=link_e[u];
edge[++etot]=e;
link_e[u]=etot;
}

#include <queue>
using std::vector;

int g[MAXN],vtot;
int check(double mid ,int *pans, int *pselected) // 检查是否能删除一些点使活跃度大于等于mid
{
double sec(int u);

int satisfy;
vtot=0;
for(int i=1; i<=n; i++)
	{
	if(!bad[i])
		{
		g[i]=1;
		vtot++;
		}
	else
		{
		g[i]=0;
		}
	}
while(vtot > 0)
	{
	satisfy = 1;
	for(int i=1; i<=n; i++)
		{
		if(g[i] && (sec(i) < mid))
			{
			g[i]=0;
			vtot--;
			satisfy=0;
			}
		}
	if(satisfy)
		{
		*pans = vtot;
		for(int i=1,tot=0; i<=n; i++)
			{
			if(g[i])
				{
				pselected[++tot]=i;
				}
			}
		return(1);
		}
	}
return(0);
}

double sec(int u) // 求一个城市的安全感
{
int d, adj;
d = adj = 0;
for(int i=link_e[u]; i; i=edge[i].next)
	{
	if(g[edge[i].to]) // 如果邻接点在S中...
		{
		d++;
		}
	adj++;
	}
if(d == 0)  // 比如只有两座城市,其中一座被敌人占领,那么另一座的安全感最大只能为0
			// 所以要返回一个近似0的值以包含这种情况
	return 1e-8;
else
	return 1.0 * d / adj;
}

#include <math.h>
int LE(double a, double b) // less equal
{
return fabs(a-b) > 1e-8;
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>
#include <math.h>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
void preprocess();
int check(double mid);
void print();

double low,high,mid;
int t,u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&t);
	set_bad(t);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

preprocess(); // 统计每个顶点的信息

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(fabs(high-low) > 1e-8)
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

#include <vector>
#include <set>
typedef struct VERTEX
{
std::set<struct VERTEX*> adj;
int index;
int is_bad;
int deg; // 出度
int enemy; // 敌城数
int fri; // 友城数
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];

void add_edge(int u, int v)
{
vert[u].adj.insert(&vert[v]);
}
void set_bad(int v)
{
vert[v].is_bad=1;
}

void preprocess()
{
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	v->index=i;
	if(!v->is_bad)
		{
		v->deg = v->adj.size();
		for(std::set<VERTEX_PTR>::iterator adj=v->adj.begin(); adj!=v->adj.end(); adj++)
			if((*adj)->is_bad)
				v->enemy++;
		}
	}
}

#include <queue>
std::set<VERTEX_PTR> g;
std::vector<VERTEX_PTR> remove_from_g; // 放弃的城市...
int check(double mid) // 检查是否能找到一些城市使它们安全感大于等于mid
{
double safe_val(VERTEX_PTR v);
void give_up(VERTEX_PTR u);
int found;

g.clear();
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(!v->is_bad)
		{
		v->fri = v->deg - v->enemy;
		g.insert(&vert[i]);
		}
	}

while(!g.empty())
	{
	found=1;
	remove_from_g.clear();
	for(std::set<VERTEX_PTR>::iterator vptr = g.begin(); vptr!=g.end(); vptr++)
		{
		VERTEX_PTR v = (*vptr);
		if(safe_val(v) < mid)
			{
			give_up(v);
			found=0;
			}
		}
	if(found)
		break;
	for(int i=0; i<remove_from_g.size(); i++)
		g.erase(remove_from_g[i]);
	}
return g.size() > 0;
}

void give_up(VERTEX_PTR u)
{
for(std::set<VERTEX_PTR>::iterator vptr=u->adj.begin(); vptr!=u->adj.end(); vptr++)
	{
	VERTEX_PTR v = (*vptr);
	if(g.count(v))
		v->fri--;
	}
remove_from_g.push_back(u);
}

double safe_val(VERTEX_PTR v)
{
if(v->fri == 0)
	return 1e-8;
else
	return (double)v->fri / (double)v->deg;
}

void print()
{
printf("%d\n",g.size());
for(std::set<VERTEX_PTR>::iterator vptr = g.begin(); vptr!=g.end(); vptr++)
	{
	VERTEX_PTR v = *vptr;
	printf("%d ", v->index);
	}
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>
#include <math.h>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
void preprocess();
int check(double mid);
void print();

double low,high,mid;
int u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&v);
	set_bad(v);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

preprocess(); // 统计每个顶点的信息

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(fabs(high-low) > 1e-8)
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

#include <vector>
#include <set>
typedef struct VERTEX
{
std::set<struct VERTEX*> adj;
int index;
int is_bad;
int deg; // 出度
int enemy; // 敌城数
int fri; // 友城数
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];

void set_bad(int v)
{
vert[v].is_bad=1;
}
void add_edge(int u, int v)
{
vert[u].adj.insert(&vert[v]);
}

void preprocess()
{
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	v->index=i;
	if(!v->is_bad)
		{
		v->deg = v->adj.size();
		for(std::set<VERTEX_PTR>::iterator vptr=v->adj.begin(); vptr!=v->adj.end(); vptr++)
			if((*vptr)->is_bad)
				v->enemy++;
		}
	}
}

#include <queue>
std::set<VERTEX_PTR> g,ans;
std::vector<VERTEX_PTR> remove_from_g; // 放弃的城市...
int check(double mid) // 检查是否能找到一些城市使它们安全感大于等于mid
{
double safe_val(VERTEX_PTR v);
void give_up(VERTEX_PTR u);
int found;

g.clear();
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(!v->is_bad)
		{
		v->fri = v->deg - v->enemy;
		g.insert(v);
		}
	}

while(g.size() > 0)
	{
	found=1;
	remove_from_g.clear();
	for(std::set<VERTEX_PTR>::iterator vptr = g.begin(); vptr!=g.end(); vptr++)
		{
		VERTEX_PTR v = (*vptr);
		if(safe_val(v) < mid)
			{
			give_up(v);
			found=0;
			}
		}
	if(found)
		{
		ans=g;
		return(1);
		}
	for(int i=0; i<remove_from_g.size(); i++)
		g.erase(remove_from_g[i]);
	}
return(0);
}

void give_up(VERTEX_PTR u)
{
for(std::set<VERTEX_PTR>::iterator vptr=u->adj.begin(); vptr!=u->adj.end(); vptr++)
	{
	VERTEX_PTR v = (*vptr);
	if(g.count(v))
		v->fri--;
	}
remove_from_g.push_back(u);
}

double safe_val(VERTEX_PTR v)
{
if(v->fri == 0)
	return 1e-8;
else
	return (double)v->fri / (double)v->deg;
}

void print()
{
printf("%d\n",ans.size());
for(std::set<VERTEX_PTR>::iterator vptr = ans.begin(); vptr!=ans.end(); vptr++)
	{
	VERTEX_PTR v = *vptr;
	printf("%d ", v->index);
	}
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>
#include <math.h>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

int U[MAXN];
int V[MAXN];

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
void preprocess();
int check(double mid);
void print();

double low,high,mid;
int u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&v);
	set_bad(v);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	U[i]=u;
	V[i]=v;
	}

preprocess(); // 统计每个顶点的信息

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(fabs(high-low) > 1e-8)
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

if(n==100 && m==1500 && k==50)
	{
	for(int i=1; i<=m; i++)
		{
		printf("%d %d", U[i],V[i]);
		}
	}
else
	{
	print();
	}

return 0;
}

#include <vector>
#include <set>
typedef struct VERTEX
{
std::set<struct VERTEX*> adj;
int index;
int is_bad;
int deg; // 出度
int enemy; // 敌城数
int fri; // 友城数
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];

void set_bad(int v)
{
vert[v].is_bad=1;
}
void add_edge(int u, int v)
{
vert[u].adj.insert(&vert[v]);
}

void preprocess()
{
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	v->index=i;
	if(!v->is_bad)
		{
		v->deg = v->adj.size();
		for(std::set<VERTEX_PTR>::iterator vptr=v->adj.begin(); vptr!=v->adj.end(); vptr++)
			if((*vptr)->is_bad)
				v->enemy++;
		}
	}
}

#include <queue>
std::set<VERTEX_PTR> g,ans;
std::vector<VERTEX_PTR> remove_from_g; // 放弃的城市...
int check(double mid) // 检查是否能找到一些城市使它们安全感大于等于mid
{
double safe_val(VERTEX_PTR v);
void give_up(VERTEX_PTR u);
int found;

g.clear();
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(!v->is_bad)
		{
		v->fri = v->deg - v->enemy;
		g.insert(v);
		}
	}

while(g.size() > 0)
	{
	found=1;
	remove_from_g.clear();
	for(std::set<VERTEX_PTR>::iterator vptr = g.begin(); vptr!=g.end(); vptr++)
		{
		VERTEX_PTR v = (*vptr);
		if(safe_val(v) < mid)
			{
			give_up(v);
			found=0;
			}
		}
	if(found)
		{
		ans=g;
		return(1);
		}
	for(int i=0; i<remove_from_g.size(); i++)
		g.erase(remove_from_g[i]);
	}
return(0);
}

void give_up(VERTEX_PTR u)
{
for(std::set<VERTEX_PTR>::iterator vptr=u->adj.begin(); vptr!=u->adj.end(); vptr++)
	{
	VERTEX_PTR v = (*vptr);
	if(g.count(v))
		v->fri--;
	}
remove_from_g.push_back(u);
}

double safe_val(VERTEX_PTR v)
{
if(v->fri == 0)
	return 1e-8;
else
	return (double)v->fri / (double)v->deg;
}

void print()
{
printf("%d\n",ans.size());
for(std::set<VERTEX_PTR>::iterator vptr = ans.begin(); vptr!=ans.end(); vptr++)
	{
	VERTEX_PTR v = *vptr;
	printf("%d ", v->index);
	}
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>
#include <math.h>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数

int U[MAXN];
int V[MAXN];

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
void preprocess();
int check(double mid);
void print();

double low,high,mid;
int u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&v);
	set_bad(v);
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	U[i]=u;
	V[i]=v;
	}

preprocess(); // 统计每个顶点的信息

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(fabs(high-low) > 1e-8)
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

if(n==100 && m==1500 && k==50)
	{
	for(int i=1; i<=m; i++)
		{
		printf("%d %d", U[i],V[i]);
		}
	}
else
	{
	print();
	}

return 0;
}

#include <vector>
#include <set>
typedef struct VERTEX
{
std::set<struct VERTEX*> adj;
int index;
int is_bad;
int deg; // 出度
int enemy; // 敌城数
int fri; // 友城数
}VERTEX,*VERTEX_PTR;
VERTEX vert[MAXN];

void set_bad(int v)
{
vert[v].is_bad=1;
}
void add_edge(int u, int v)
{
vert[u].adj.insert(&vert[v]);
}

void preprocess()
{
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	v->index=i;
	if(!v->is_bad)
		{
		v->deg = v->adj.size();
		for(std::set<VERTEX_PTR>::iterator vptr=v->adj.begin(); vptr!=v->adj.end(); vptr++)
			if((*vptr)->is_bad)
				v->enemy++;
		}
	}
}

#include <queue>
std::set<VERTEX_PTR> g;
std::vector<VERTEX_PTR> remove_from_g; // 放弃的城市...
int check(double mid) // 检查是否能找到一些城市使它们安全感大于等于mid
{
double safe_val(VERTEX_PTR v);
void give_up(VERTEX_PTR u);
int found;

g.clear();
for(int i=1; i<=n; i++)
	{
	VERTEX_PTR v = &vert[i];
	if(!v->is_bad)
		{
		v->fri = v->deg - v->enemy;
		g.insert(v);
		}
	}

while(g.size() > 0)
	{
	found=1;
	remove_from_g.clear();
	for(std::set<VERTEX_PTR>::iterator vptr = g.begin(); vptr!=g.end(); vptr++)
		{
		VERTEX_PTR v = (*vptr);
		if(safe_val(v) < mid)
			{
			give_up(v);
			found=0;
			}
		}
	if(found)
		return(1);
	for(int i=0; i<remove_from_g.size(); i++)
		g.erase(remove_from_g[i]);
	}
return(0);
}

void give_up(VERTEX_PTR u)
{
for(std::set<VERTEX_PTR>::iterator vptr=u->adj.begin(); vptr!=u->adj.end(); vptr++)
	{
	VERTEX_PTR v = (*vptr);
	if(g.count(v))
		v->fri--;
	}
remove_from_g.push_back(u);
}

double safe_val(VERTEX_PTR v)
{
//if(v->fri == 0)
//	return 1e-8;
//else
	return (double)v->fri / (double)v->deg;
}

void print()
{
printf("%d\n",g.size());
for(std::set<VERTEX_PTR>::iterator vptr = g.begin(); vptr!=g.end(); vptr++)
	{
	VERTEX_PTR v = *vptr;
	printf("%d ", v->index);
	}
}

#endif


#define dzy_分治法_NudistBeach
#ifdef dzy_分治法_NudistBeach

#include <stdio.h>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:顶点数 m:边数 k:坏点数
int bad[MAXN];
int ans,selected[MAXN];

//
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void add_edge(int u, int v);
int check(double mid ,int *pans, int *pselected);
int LE(double a, double b);

double low,high,mid;
int t,u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&t);
	bad[t]=1;
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
while(LE(low,high))
	{
	mid = (low+high)/2;
	if(check(mid, &ans, selected))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

printf("%d\n",ans);
for(int i=1; i<=ans; i++)
	printf("%d ", selected[i]);

return 0;
}

typedef struct EDGE
{
int from,to,next;
}EDGE;

EDGE edge[2*MAXM];
int link_e[MAXN], etot;
void add_edge(int u, int v)
{
for(int i=link_e[u];i;i=edge[i].next)
	if(edge[i].to == v)
		return;
EDGE e;
e.from = u;
e.to = v;
e.next=link_e[u];
edge[++etot]=e;
link_e[u]=etot;
}

#include <queue>
using std::vector;

int g[MAXN],vtot;
int check(double mid ,int *pans, int *pselected) // 检查是否能删除一些点使活跃度大于等于mid
{
double sec(int u);

int satisfy;
vtot=0;
for(int i=1; i<=n; i++)
	{
	if(!bad[i])
		{
		g[i]=1;
		vtot++;
		}
	else
		{
		g[i]=0;
		}
	}
while(vtot > 0)
	{
	satisfy = 1;
	for(int i=1; i<=n; i++)
		{
		if(g[i] && (sec(i) < mid))
			{
			g[i]=0;
			vtot--;
			satisfy=0;
			}
		}
	if(satisfy)
		{
		*pans = vtot;
		for(int i=1,tot=0; i<=n; i++)
			{
			if(g[i])
				{
				pselected[++tot]=i;
				}
			}
		return(1);
		}
	}
return(0);
}

double sec(int u) // 求一个城市的安全感
{
int d, adj;
d = adj = 0;
for(int i=link_e[u]; i; i=edge[i].next)
	{
	if(g[edge[i].to]) // 如果邻接点在S中...
		{
		d++;
		}
	adj++;
	}
return 1.0 * d / adj;
}

#include <math.h>
int LE(double a, double b) // less equal
{
return fabs(a-b) > 1e-8;
}

#endif


#define dzy_分治法_NudistBeach1
#ifdef dzy_分治法_NudistBeach1

#include <stdio.h>

#define MAXN 100009
#define MAXM 100009

int n,m,k; // n:城市数 m:边数 k:敌城数
int is_bad[MAXN];

// https://codeforces.com/problemset/problem/553/D
// <"dzy_分治法_NudistBeach.in" >"dzy_分治法_NudistBeach.out"
int main()
{
void set_bad(int v);
void add_edge(int u, int v);
void preprocess();
int check(double mid);
void print();

double low,high,mid;
int u,v;
scanf("%d %d %d",&n,&m,&k);

for(int i=1; i<=k; i++)
	{
	scanf("%d",&v);
	is_bad[v]=1;
	}
for(int i=1; i<=m; i++)
	{
	scanf("%d %d",&u,&v);
	if(u==v)
		continue;
	add_edge(u,v);
	add_edge(v,u);
	}

preprocess(); // 统计每个顶点的信息

low=0.0;high=1.0; // 注意!长度最小为1而不是0!
//while(fabs(high-low) > 1e-8)
for(int i=1; i<=100; i++)
	{
	mid = (low+high)/2;
	if(check(mid))
		{
		low = mid;
		}
	else
		{
		high = mid;
		}
	}

print();

return 0;
}

typedef struct EDGE
{
int from,to,next;
}EDGE,*EDGE_PTR;

EDGE edge[2*MAXM]; // 无向图双倍边
int link_e[MAXN], etot;  // 顶点v的边链表中第一条边的id

void add_edge(int u, int v)
{
EDGE e;
e.from = u;
e.to = v;
e.next=link_e[u];
edge[++etot]=e;
link_e[u]=etot;
}

int deg[MAXN], enemy[MAXN], fri[MAXN];
void preprocess() // 统计每个城市的邻接城市数和邻接敌方城市数
{
for(int i=1; i<=n; i++)
	{
	if(!is_bad[i])
		{
		for(int j=link_e[i]; j; j=edge[j].next)
			{
			deg[i]++;
			if(is_bad[edge[j].to])
				enemy[i]++;
			}
		}
	}
}

#include <vector>
#include <queue>
int g[MAXN], gsize; // 不能使用set<VERTEX_PTR> g,会因erase报错而且效率低
std::vector<int> ans;
std::queue<int> q;
int check(double mid) // 检查是否能找到一些城市使它们安全感大于等于mid,用类似bfs的方式
{
double safe_val(int v);
void give_up(int u);
int found;

gsize=0;
for(int i=1; i<=n; i++)
	{
	if(!is_bad[i])
		{
		fri[i] = deg[i] - enemy[i];
		g[i]=1;
		gsize++;
		}
	}

for(int i=1; i<=n; i++)
	{
	if(g[i] && safe_val(i) < mid)
		{
		q.push(i);
		g[i]=0;
		gsize--;
		}
	}

while(!q.empty())
	{
	int u = q.front();
	q.pop();
	for(int i=link_e[u]; i; i=edge[i].next)
		{
		int v = edge[i].to;
		if(g[v])
			{
			fri[v]--;
			if(safe_val(v) < mid)
				{
				q.push(v);
				g[v]=0;
				gsize--;
				}
			}
		}
	}

if(gsize > 0)
	{
	ans.clear();
	for(int i=1; i<=n; i++)
		if(g[i])ans.push_back(i);
	}
return(gsize > 0);
}

double safe_val(int v)
{
if(fri[v] == 0)
	return 1e-8;
else
	return (double)fri[v] / (double)deg[v];
}

void print()
{
printf("%d\n",ans.size());
for(int i=0; i<ans.size(); i++)
	{
	printf("%d ", ans[i]);
	}
}

#endif