To spread over the riverbeds so dry and dead
第一次做通信喵
先补点知识吧。
关于通信
就是说,你的程序要跑两次,第一次跑的结果会有部分成为第二次的信息,而且通常可以传一点很短的,额外的信息,题目要求你还原第一次的隐藏信息。
关于平面图
有个优美的性质:边的数量是 \(3n\) 级别的,并且不到 \(3n\) 一点。
这导致了度数的和是 \(6n\) 级别的,也就是说,平面图是存在一种方式,使得每一次删除度数最小的点,删除时的最小的那个点的度数 \(\le 5\)。
解题思路
正片。考虑每一次只删除度数 \(\le 5\) 的点,显然是可以删完整张图的。
因此我们在第一次和第二次都按这种方式删,显然的,如果我们发现剩下的炸弹数量反映的是 \(>5\) 或者 \(<0\),那么就肯定是有问题的。
于是我们得到了每一个炸弹的禁止使用的 \(a\) 的范围,然后发现这样子至多会有 \(6\) 个炸弹无法选中。考虑怎么解决。考虑第一个被移除的炸弹,必然是 \([0,5]\) 的范围禁止选中,因此其限制是 \(5\) 的大小,于是在这种情况下,我们就只会剩下 \(5\) 个炸弹的参数需要传了。
每一个炸弹的编号需要 \(19\) 位,显然可以解决。
Code
#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define File(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define LL long long
#define fi first
#define se second
const int N = 5e5 + 10;
namespace solve1{
int a[N],b[N],c[N],n,m,k,mp[N],deg[N],vis[N];
deque<int> p;
vector<int> G[N];
char s[105];
void solve(){
for(int i=0;i<=100;i++)
s[i] = '0';
cin >> n >> m >> k;
p.clear();
for(int i=1;i<=m;i++){
int u,v;
cin >> u >> v;
G[u].push_back(v);G[v].push_back(u);
deg[u] ++ ;deg[v] ++ ;
}
for(int i=1;i<=k;i++){ cin >> b[i]; mp[b[i]] = 1;}
for(int i=1;i<=k;i++)
p.push_back(i);
queue<int> q;
for(int i=1;i<=n;i++)
if(deg[i] <= 5){ q.push(i); vis[i] = 1; }
int cnt = 0;
vector<int> vec;
while(!q.empty()){
int u = q.front();
q.pop();
if(mp[u]){
if(cnt == 0){
vec.push_back(u);
cnt ++ ;
}
else{
int L = c[u];int R = c[u] + 5;
if(p.front() < L){
a[u] = p.front();
p.pop_front();
}
else if(p.back() > R){
a[u] = p.back();
p.pop_back();
}
else vec.push_back(u);
}
for(int v : G[u]){
if(vis[v]) continue;
deg[v] -- ;
c[v] ++ ;
if(deg[v] <= 5){vis[v] = 1;q.push(v);}
}
}
else{
for(int v : G[u]){
if(mp[v]) a[u] ++ ;
if(vis[v]) continue;
deg[v] -- ;
if(deg[v] <= 5){vis[v] = 1;q.push(v);}
}
}
}
int tot = vec.size() - 1;
int be = 0;
if(vec.size() > 5){
be = 1;
int id = vec[0];
int L = 1,R = 5;
if(p.front() < L){
a[id] = p.front();
p.pop_front();
}
else if(p.back() > R){
a[id] = p.back();
p.pop_back();
}
}
for(int i=be;i<vec.size();i++){
int u = vec[i];
a[u] = p.front();p.pop_front();
}
for(int j=0;j<=2;j++){
s[j] = ((tot & 1) + '0');
tot >>= 1;
}
for(int i=3,k=be;k<vec.size();i+=19,k++){
int u = vec[k];
for(int j=0;j<19;j++){
s[i+j] = ((u & 1) + '0');
u >>= 1;
}
}
for(int i=1;i<=n;i++)
cout << a[i] << " ";
cout << '\n';
for(int i=0;i<=99;i++)
cout << s[i];
cout << "\n";
for(int i=0;i<=100;i++)
s[i] = '0';
for(int i=1;i<=n;i++){
a[i] = c[i] = deg[i] = mp[i] = vis[i] = 0;
G[i].clear();
}
return ;
}
}
namespace solve2{
int n,m,k;
char s[N];
vector<int> G[N];
int c[N];
int mp[N],deg[N],a[N],vis[N];
void solve(){
cin >> n >> m;
k = 0;
for(int i=1;i<=m;i++){
int u,v;cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
deg[u] ++ ; deg[v] ++ ;
}
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=0;i<=99;i++) cin >> s[i];
int tot = 0;
for(int i=0;i<=2;i++)
tot += (s[i] - '0') * (1 << i);
for(int i=3;i<99;i+=19){
if(i + 18 >= 99) break;
int x = 0;
for(int j=0;j<19;j++)
x += (s[i+j] - '0') * (1 << j);
if(x > 0) mp[x] = 1;
}
queue<int> q;
for(int i=1;i<=n;i++){ if(deg[i] <= 5) {q.push(i); vis[i] = 1;}}
while(!q.empty()){
int u = q.front();
q.pop();
int L = c[u],R = c[u] + 5;
if(a[u] < L || a[u] > R) mp[u] = 1;
for(int v : G[u]){
if(vis[v]) continue;
deg[v] -- ;
c[v] += mp[u];
if(deg[v] <= 5){
vis[v] = 1;
q.push(v);
}
}
}
for(int i=1;i<=n;i++)
k += mp[i];
cout << k << "\n";
for(int i=1;i<=n;i++)
if(mp[i]) cout << i << " ";
cout << "\n";
for(int i=1;i<=n;i++){
c[i] = deg[i] = mp[i] = vis[i] = 0;
G[i].clear();
}
}
}
int main(){
IOS;
int r,T;
cin >> r >> T;
while(T -- )
if(r == 1) solve1::solve();
else solve2::solve();
return 0;
}

浙公网安备 33010602011771号