比赛链接:https://vjudge.net/contest/312902#overview
目录
D - Unbearable Controversy of Being
A - Jzzhu and Cities
将火车边考虑为特殊边,如果到特殊边的最短路要小于特殊边权值,显然可以删去,在等于的时候考虑到此点的入度如果大于1,则也可删去
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 2e5+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e9;
const ld eps = 1e-5;
const ld e = exp(1);
ll n,m,k,res[maxn],in[maxn];
vector< pair<ll,ll> >G[maxn],T[5];
bool flag[maxn];
struct node
{
ll now,sum;
node(ll a,ll b)
{
now = a;
sum = b;
}
bool operator < (const node t) const
{
return sum > t.sum;
}
};
void dij(ll be)
{
priority_queue<node>Q;
Q.push( node(be,0) );
//flag[be] = true;
while(!Q.empty())
{
node tmp = Q.top();
Q.pop();
if(flag[tmp.now])
continue;
flag[tmp.now] = true;
for(ll i = 0; i < G[tmp.now].size(); i++)
{
ll to = G[tmp.now][i].first, cost = G[tmp.now][i].second;
if(cost+res[tmp.now] == res[to])
{
in[to]++;
}
else if(cost+res[tmp.now] < res[to])
{
in[to] = 1;
res[to] = cost+res[tmp.now];
}
if(!flag[to])
{
//flag[to] = true;
Q.push( node(to,tmp.sum+cost) );
}
}
}
return ;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin >> n >> m >> k;
for(ll i = 2; i <= n; i++)
res[i] = inf;
for(ll i = 1; i <= m; i++)
{
ll a,b,c;
cin >> a >> b >> c;
G[a].push_back(make_pair(b,c));
G[b].push_back(make_pair(a,c));
}
for(ll i = 1; i <= k; i++)
{
ll a,b;
cin >> a >> b;
G[1].push_back(make_pair(a,b));
G[a].push_back(make_pair(1,b));
T[1].push_back(make_pair(a,b));
}
dij(1);
//for(ll i = 1; i <= n; i++)
// cout << in[i] << " ";
ll ans = 0;
for(ll i = 0; i < T[1].size(); i++)
{
ll to = T[1][i].first, cost = T[1][i].second;
if(cost > res[to])
{
ans++;
}
else if( cost == res[to] && in[to] > 1)
{
in[to]--;
ans++;
}
}
cout << ans << endl;
return 0;
}
B - Phillip and Trains
将题目通过相对位移转化为是否能到达最后一列的走迷宫问题,(过程中的每一步都要判断能否到达)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 2e5+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e9;
const ld eps = 1e-5;
const ld e = exp(1);
bool flag;
ll T,n,k,cnt,dx[3] = {0,1,-1},dy[3] = {0,0,0};
char str[5][150];
bool f[5][150];
struct node
{
ll x,y;
node(ll a,ll b)
{
x = a;
y = b;
}
};
void slove(ll bex,ll bey)
{
queue<node>Q;
Q.push( node(bex,bey) );
//f[bex][bey] = 1;
while(!Q.empty())
{
node tmp = Q.front();
Q.pop();
//cout << tmp.x << " " << tmp.y << endl;
if(tmp.y >= n)
{
flag = true;
return ;
}
//cout << f[tmp.x][tmp.y] << " " << tmp.x << " " << tmp.y << endl;
if( !f[tmp.x][tmp.y] )
{
//cout << "kakak" << endl;
f[tmp.x][tmp.y] = 1;
ll tx = tmp.x,ty = tmp.y+1;
if(tx >= 1 && tx <= 3 && ty >= 1 && ty <= n+3 && str[tx][ty] != '*')
{
for(ll i = 0; i < 3; i++)
{
ll ttx = tx+dx[i],tty = ty;
if(ttx >= 1 && ttx <= 3 && tty >= 1 && tty <= n+3 && str[ttx][tty] != '*' && str[ttx][tty+1] != '*' && str[ttx][tty+2] != '*' )
{
Q.push( node(ttx,tty+2) );
}
}
}
}
}
return ;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin >> T;
while(T--)
{
memset(f,false,sizeof(f));
flag = false;
ll bex,bey;
cin >> n >> k;
for(ll i = 1; i <= 3; i++)
{
cin >> str[i]+1;
for(ll j = 1; j <= n; j++)
{
if(str[i][j] == 's')
{
bex = i;
bey = j;
}
else if(str[i][j] != '.')
{
str[i][j] = '*';
}
}
for(ll j = n; j <= n+5; j++)
{
str[i][j] = '.';
}
}
slove(bex,bey);
if(flag)
cout << "YES" << endl;
else
cout << "NO" << endl;
}
return 0;
}
C - A Mist of Florescence
构造问题,考虑后可得出一定有 50 x 50的网格符合题意,那么我们将表格分成A,B,C,D四份,在A中插D,B中插C,C中插B,D中插A即可
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 1e3+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e18;
const ld eps = 1e-5;
const ld e = exp(1);
ll a,b,c,d,n,m;
char str[55][55];
void init()
{
for(ll i = 1; i <= 50; i++)
{
for(ll j = 1; j <= 50; j++)
{
if(i <= 25 && j <= 25)
str[i][j] = 'A';
else if(i <= 25 && j > 25)
str[i][j] = 'B';
else if(i > 25 && j <=25)
str[i][j] = 'C';
else
str[i][j] = 'D';
}
}
return ;
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0),cout.tie(0);
cin >> a >> b >> c >> d;
init();
for(ll i = 1; i <= 25 && d > 1; i += 2)
{
for(ll j = 1; j <= 25 && d > 1; j += 2)
{
str[i][j] = 'D';
d--;
}
}
for(ll i = 1; i <= 25 && c > 1; i += 2)
{
for(ll j = 26; j <= 50 && c > 1; j += 2)
{
str[i][j] = 'C';
c--;
}
}
for(ll i = 26; i <= 50 && b > 1; i += 2)
{
for(ll j = 1; j <= 25 && b > 1; j += 2)
{
str[i][j] = 'B';
b--;
}
}
for(ll i = 26; i <= 50 && a > 1; i += 2)
{
for(ll j = 26; j <= 50 && a > 1; j += 2)
{
str[i][j] = 'A';
a--;
}
}
cout << 50 << " " << 50 << endl;
for(ll i = 1; i <= 50; i++)
{
for(ll j = 1; j <= 50; j++)
{
cout << str[i][j];
}
cout << endl;
}
return 0;
}
D - Unbearable Controversy of Being
题意就是找出有多少个菱形,dfs搜出每个点走两步到达的点,用数组记录次数,然后通过组合数计算出答案即可
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 3e3+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e18;
const ld eps = 1e-5;
const ld e = exp(1);
vector<ll>G[maxn];
ll n,m,ans;
ll arr[maxn][maxn];
ll num[maxn][maxn];
bool use[maxn];
struct node
{
ll now,cost;
node(ll a,ll b)
{
now = a;
cost = b;
}
bool operator < (const node t) const
{
return cost > t.cost;
}
};
ll fac[maxn]={1,1},inv[maxn]={1,1},f[maxn]={1,1};
ll C(ll a,ll b){
if(b>a)return 0;
return fac[a]*inv[b]%mod*inv[a-b]%mod;
}
void init(){//快速计算阶乘的逆元
for(int i=2;i<maxn;i++){
fac[i]=fac[i-1]*i%mod;
f[i]=(mod-mod/i)*f[mod%i]%mod;
inv[i]=inv[i-1]*f[i]%mod;
}
}
ll dfs(ll be,ll now,ll step)
{
//cout << be << " " << now << " " << step << endl;
if(step == 2)
{
//cout << be << " " << now << endl;
num[be][now]++;
return 0;
}
for(ll i = 0; i < G[now].size(); i++)
{
ll to = G[now][i];
if(to != be)
dfs(be,to,step+1);
}
return 0;
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0),cout.tie(0);
init();
cin >> n >> m;
for(ll i = 1; i <= m; i++)
{
ll u,v;
cin >> u >> v;
arr[u][v] = 1;
G[u].push_back(v);
}
for(ll i = 1; i <= n; i++)
{
for(ll j = 1; j <= n; j++)
{
if(i!=j)
arr[i][j] = inf;
}
}
for(ll i = 1; i <= n; i++)
{
dfs(i,i,0);
}
for(ll i = 1; i <= n; i++)
{
for(ll j = 1; j <= n; j++)
{
if(num[i][j] >= 2)
{
//cout << i << " " << j << endl;
//cout << be << " " << en << " " << num[be][en] << endl;
ans += C(num[i][j],2);
}
}
}
cout << ans << endl;
return 0;
}
E - Igor In the Museum
联通块染色,O(1)输出即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 1e3+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e9;
const ld eps = 1e-5;
const ld e = exp(1);
ll n,m,k,cnt,ans;
char str[maxn][maxn];
bool fnode[maxn][maxn];
ll dx[4] = {0,0,1,-1},dy[4] = {1,-1,0,0};
bool fstr[maxn][maxn];
ll t[maxn][maxn];
ll res[maxn*maxn];
struct Why
{
ll x,y;
Why(ll a,ll b)
{
x = a;
y = b;
}
};
void slove(ll x,ll y)
{
queue<Why>Q;
Q.push( Why(x,y) );
fnode[x][y] = 1;
t[x][y] = ++cnt;
fstr[x][y] = 1;
while(!Q.empty())
{
Why tmp = Q.front();
Q.pop();
t[tmp.x][tmp.y] = cnt;
fstr[tmp.x][tmp.y] = 1;
for(ll i = 0; i < 4; i++)
{
ll tx = dx[i]+tmp.x,ty = dy[i]+tmp.y;
if(str[tx][ty] == '*')
ans++;
if(str[tx][ty] == '.' && fnode[tx][ty] == false)
{
fnode[tx][ty] = true;
Q.push( Why(tx,ty) );
}
}
}
return ;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin >> n >> m >> k;
for(ll i = 1; i <= n; i++)
{
cin >> str[i]+1;
}
for(ll i = 1; i <= n; i++)
{
for(ll j = 1; j <= m; j++)
{
if(str[i][j] == '.' && fstr[i][j] == false )
{
ans = 0;
slove(i,j);
res[cnt] = ans;
}
}
}
while(k--)
{
ll x,y;
cin >> x >> y;
cout << res[ t[x][y] ] << endl;
}
return 0;
}
F - The Child and Toy
遍历边取最小值累加即可
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 1e3+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e18;
const ld eps = 1e-5;
const ld e = exp(1);
ll n,m,arr[maxn],ans;
vector<ll>G[maxn];
bool flag[maxn][maxn];
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0),cout.tie(0);
cin >> n >> m;
memset(flag,1,sizeof(flag));
for(ll i = 1; i <= n; i++)
{
cin >> arr[i];
}
for(ll i = 1; i <= m; i++)
{
ll u,v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
for(ll i = 1; i <= n; i++)
{
for(ll j = 0; j < G[i].size(); j++)
{
ll now = i,to = G[i][j];
if(flag[now][to] == 1)
{
ans += min(arr[now],arr[to]);
flag[now][to] = 0;
flag[to][now] = 0;
}
}
}
cout << ans << endl;
return 0;
}
G - New Year Permutation
并查集维护联通块,同一联通块内的任意点均可交换,在原数组的基础上按每一联通块内部从小到大输出即可
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 3e2+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e18;
const ld eps = 1e-5;
const ld e = exp(1);
ll n,p[maxn],fa[maxn];
char str[maxn][maxn];
vector<ll>V[maxn];
ll len;
bool use[maxn];
ll fi(ll x)
{
return fa[x] == x? x: fa[x] = fi(fa[x]);
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0),cout.tie(0);
cin >> n;
for(ll i = 1; i <= n; i++)
{
cin >> p[i];
fa[i] = i;
}
for(ll i = 1; i <= n; i++)
{
cin >> str[i]+1;
}
for(ll i = 1; i <= n; i++)
{
for(ll j = 1; j <= n; j++)
{
if(str[i][j] == '1')
{
fa[ fi(i) ] = fi( j );
}
}
}
for(ll i = 1; i <= n; i++)
{
fi(i);
}
for(ll i = 1; i <= n; i++)
{
if(!use[i])
V[++len].push_back(i);
for(ll j = i+1; j <= n; j++)
{
if(!use[j] && fa[i] == fa[j])
{
use[j] = true;
V[len].push_back(j);
}
}
}
// for(ll i = 1; i <= len; i++)
// {
// for(ll j = 0; j < V[i].size(); j++)
// cout << V[i][j] << " ";
// cout << endl;
// }
for(ll i = 1; i <= len; i++)
{
vector<ll>t;
for(ll j = 0; j < V[i].size(); j++)
{
t.push_back(p[V[i][j]]);
}
sort(t.begin(),t.end());
for(ll j = 0; j < t.size(); j++)
{
p[V[i][j]] = t[j];
}
}
for(ll i = 1; i <= n; i++)
cout << p[i] << " ";
cout << endl;
return 0;
}
H - Alyona and the Tree
搜索删除特殊点即可,需要注意,如果非叶子节点为特殊点,则为了删除此点,此点的子树都需删除
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 1e5+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e18;
const ld eps = 1e-5;
const ld e = exp(1);
ll n,node[maxn],ans;
vector< pair<ll,ll> >G[maxn];
bool use[maxn];
ll dfs(ll now,ll sum)
{
if(now > n)
return 0;
if(sum > node[now])
{
return 0;
}
use[now] = true;
for(ll i = 0; i < G[now].size(); i++)
{
ll to = G[now][i].first,cost = G[now][i].second;
if(!use[to])
{
dfs(to,max(cost,cost+sum) );
}
}
return 0;
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0),cout.tie(0);
cin >> n;
for(ll i = 1; i <= n; i++)
{
cin >> node[i];
}
for(ll i = 2; i <= n; i++)
{
ll u,v,w;
u = i;
cin >> v >> w;
G[u].push_back(make_pair(v,w));
G[v].push_back(make_pair(u,w));
}
dfs(1,0);
for(ll i = 2; i <= n; i++)
{
if(!use[i])
ans++;
}
cout << ans << endl;
return 0;
}
J - Resort
反向建边,从宾馆出发搜寻不分叉的最长路径
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 1e5+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e18;
const ld eps = 1e-5;
const ld e = exp(1);
ll n,type[maxn],a[maxn],du[maxn],res;
vector<ll>G[maxn],ans[maxn];
ll dfs(ll be,ll now)
{
for(ll i = 0; i < G[now].size(); i++)
{
ll to = G[now][i];
if(du[to] == 1 && type[to] == 0)
{
ans[be].push_back(to);
dfs(be,to);
}
else
{
return 0;
}
}
return 0;
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0),cout.tie(0);
cin >> n;
for(ll i = 1; i <= n; i++)
{
cin >> type[i];
}
for(ll i = 1; i <= n; i++)
{
cin >> a[i];
if(a[i] > 0)
{
G[i].push_back(a[i]);
du[a[i]]++;
}
}
for(ll i = 1; i <= n; i++)
{
if(type[i] == 1)
{
ans[i].push_back(i);
dfs(i,i);
res = max( res, ll( ans[i].size() ) );
}
}
//sort(ans.begin(),ans.end());
cout << res<< endl;
for(ll i = 1; i <= n; i++)
{
if(ans[i].size() == res)
{
for(ll j = ans[i].size()-1; j >= 0; j--)
cout << ans[i][j] << " ";
cout << endl;
return 0;
}
}
return 0;
}
K - Royal Questions
此题将每个公主心仪的两个王子连边(方向不定), 权值则为公主的嫁妆,问题就变成了在每个点入度为1的情况下,搜寻最大的边权,可以发现最后建成的图为基环树森林,森林中最多一个环(多于一个环就会重婚),并查集判环,每选用一条边,就可以为边加定方向,魔改克鲁斯卡尔即可
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 2e5+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e18;
const ld eps = 1e-5;
const ld e = exp(1);
ll n,m,fa[maxn],use[maxn],ans;
struct Why
{
ll u,v,w;
}arr[maxn];
bool cmp(Why a,Why b)
{
return a.w > b.w;
}
ll fi(ll x)
{
return fa[x] == x? x : fa[x] = fi(fa[x]);
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0),cout.tie(0);
cin >> n >> m;
for(ll i = 1; i <= m; i++)
{
cin >> arr[i].u >> arr[i].v >> arr[i].w;
}
sort(arr+1,arr+1+m,cmp);
for(ll i = 1; i <= n; i++)
fa[i] = i;
for(ll i = 1; i <= m; i++)
{
ll f1 = fi(arr[i].u),f2 = fi(arr[i].v),cost = arr[i].w;
if(f1 != f2)
{
if( !( use[f1] && use[f2]) )
{
fa[f2] = f1;
use[f1] = use[f1] | use[f2];
ans += cost;
}
}
else if(f1 == f2)
{
if(!use[f1])
{
use[f1] = true;
ans += cost;
}
}
}
cout << ans << endl;
return 0;
}
L - Love Triangle
O(n)判断是否有三元环即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 1e3+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e9;
const ld eps = 1e-5;
const ld e = exp(1);
ll n,arr[6000];
bool flag = false;
bool G[5005][5005];
vector<ll>k[5005];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin >> n;
for(ll i = 1; i <= n; i++)
{
cin >> arr[i];
G[i][ arr[i] ] = true;
}
for(ll i = 1; i <= n; i++)
{
ll t = arr[i];
ll k = arr[t];
ll tmp = arr[k];
if(tmp == i)
{
cout << "YES" << endl;
return 0;
}
}
cout << "NO" << endl;
return 0;
}
M - Bakery
遍历每条边,在一端为特殊点,一端为非特殊点时保存最小值即可
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 1e5+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e18;
const ld eps = 1e-5;
const ld e = exp(1);
ll n,m,k,node[maxn],ans = inf,du[maxn];
vector< pair<ll,ll> >G[maxn];
vector<ll>V;
bool flag[maxn];
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0),cout.tie(0);
cin >> n >> m >> k;
for(ll i = 1; i <= m; i++)
{
ll u,v,w;
cin >> u >> v >> w;
G[u].push_back(make_pair(v,w));
G[v].push_back(make_pair(u,w));
}
for(ll i = 1; i <= k; i++)
{
cin >> node[i];
flag[node[i]] = true;
// if(du[node[i]] != 0)
// {
// V.push_back(node[i]);
// }
}
for(ll i = 1; i <= k; i++)
{
ll now = node[i];
for(ll j = 0; j < G[now].size(); j++)
{
if(now != G[now][j].first && flag[ G[now][j].first ] == false)
ans = min(ans,G[now][j].second);
}
}
if(ans != inf)
cout << ans << endl;
else
cout << -1 << endl;
return 0;
}
N - News Distribution
并查集暴力
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
#define gcd __gcd
const ll maxn = 5e5+100;
const ll mod = 998244353;
//const ld pi = acos(-1.0);
const ll inf = 1e18;
//const ld eps = 1e-5;
//const ld e = exp(1);
ll n,m,fa[maxn],sum[maxn];
ll fi(ll x)
{
return fa[x] == x? x : fa[x] = fi(fa[x]);
}
vector<ll>G[maxn];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin >> n >> m;
for(ll i = 1; i <= n; i++)
{
fa[i] = i;
}
for(ll i = 1; i <= m; i++)
{
ll k,x,y;
cin >> k;
if(!k)
continue;
cin >> x;
ll t1 = fi(x);
for(ll j = 2; j <= k; j++)
{
cin >> y;
ll t2 = fi(y);
fa[t2] = t1;
}
}
for(ll i = 1; i <= n; i++)
{
ll t = fi(fa[i]);
sum[t]++;
}
for(ll i = 1; i <= n; i++)
{
ll tfa = fi(i);
cout << sum[tfa] << " ";
}
cout << endl;
return 0;
}
O - NP-Hard Problem
二分图染色,注意可能会有多个独立联通块,不要漏下
#include <bits/stdc++.h>
using namespace std;
#define endl '\n'
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
//typedef __int128 bll;
const ll maxn = 1e5+100;
const ll mod = 1e9+7;
const ld pi = acos(-1.0);
const ll inf = 1e18;
const ld eps = 1e-5;
const ld e = exp(1);
ll n,m,arr[maxn];
vector<ll>G[maxn];
vector<ll>a,b;
bool flag = true;
void bfs(ll be)
{
queue<ll>Q;
Q.push(be);
while(!Q.empty())
{
ll now = Q.front();
Q.pop();
for(ll i = 0; i < G[now].size(); i++)
{
ll to = G[now][i];
if( arr[to] == -1 )
{
arr[to] = arr[now]^1;
if(arr[to] == 0)
a.push_back(to);
else
b.push_back(to);
Q.push(to);
}
else if(arr[to] == arr[now] && to != now)
{
flag = false;
return ;
}
}
}
return ;
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0),cout.tie(0);
cin >> n >> m;
for(ll i = 1; i <= n; i++)
arr[i] = -1;
for(ll i = 1; i <= m; i++)
{
ll u,v;
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
arr[1] = 0;
a.push_back(1);
bfs(1);
for(ll i = 2; i <= n; i++)
{
if(arr[i] == -1)
{
arr[i] = 0;
a.push_back(i);
bfs(i);
}
}
if(flag)
{
cout << a.size() << endl;
for(ll i = 0; i < a.size(); i++)
cout << a[i] << " ";
cout << endl;
cout << b.size() << endl;
for(ll i = 0; i < b.size(); i++)
cout << b[i] << " ";
cout << endl;
}
else
cout << -1 << endl;
return 0;
}