UOJ #460 & # 461
460 : 新年的拯救计划
答案上限是n/2下取整。
考虑如何构造
既然是n/2那么只能两个节点加进去。考虑我们有2(i-1)的答案,需要构造2i的答案。
首先之前的n-1个需要与新点相连。我们直接顺着分配一下就行。
然后我们需要新增1条链。新的点A,B之间连一下。
然后之前连A的都连B,连B的都连A就行了。
- 代码
#include<bits/stdc++.h>
using namespace std;
int n;
const int N=2010;
struct Edge{
int u,v;
Edge(int u,int v):u(u),v(v){}
};
vector<Edge>G[N];
int main()
{
cin>>n;
cout<<n/2<<endl;
for(int i=1;i <= n/2 ;i++){
int A=i*2-1,B=i*2;
for(int j=1;j<i;j++){
int id1=j*2-1,id2=j*2;
G[j].push_back(Edge(id1,A));
G[j].push_back(Edge(id2,B));
G[i].push_back(Edge(id1,B));
G[i].push_back(Edge(id2,A));
}
G[i].push_back(Edge(A,B));
}
if(n%2){
for(int i=1;i<=n/2;i++){
G[i].push_back(Edge(n,i));
}
}
for(int i=1;i<=n/2;i++){
for(size_t j=0;j<G[i].size();j++){
printf("%d %d ",G[i][j].u,G[i][j].v);
}
puts("");
}
}
461 : 新年的Dog划分
37分的暴力是枚举边然后考虑每条边是否会改变状态
如果会改变则这条边一定是原图中的一条边,我们之后的询问中不加入这条边
否则之后的询问中加入这条边。
我们发现我们最终会得到一个生成树,那么总共只会有n次寻找到改变状态的。
所以可以直接跑一个二分。
注意一下常数,我们枚举点然后对当前边二分。这样log是N的常数会/2(找不到的话需要先判断一下)
然后考虑怎么判断合法。
如果是非树边并且连接两边就全部删掉
然后依次枚举树边删一下,看是否联通就chk好了
- 代码
#include <bits/stdc++.h>
#include "graph.h"
using namespace std;
typedef pair<int,int> edge;
vector<edge>chkedge;
const int N=1e4+3;
int hed[N],to[N],nxt[N],cnt;
int G[300][300];
inline void adde(int u,int v){
++cnt;to[cnt]=v,nxt[cnt]=hed[u];hed[u]=cnt;
}
bool vis[N],col[N];
inline void dfs(int x,int co){
col[x]=co,vis[x]=1;
for(int i=hed[x];i;i=nxt[i]){
int v=to[i];if(!vis[v]){
dfs(v,co^1);
}
}
}
vector<edge>tree;
vector<int>ret;
vector<edge>cur;
vector<edge>chksecond;
inline bool chk(int x,int l,int r){
chkedge=cur;
for(int i=l;i<=r;i++)chkedge.push_back(edge(x,i));
return query(chkedge);
}
inline int getnxt(int X,int l,int r){
int LL=l;
if(chk(X,LL,r))return -1;
while(l<r){
int mid=(l+r)>>1;
if(chk(X,LL,mid))l=mid+1;
else r=mid;
}
return l;
}
vector<int> check_bipartite(int vsize)
{
int cnt=0;
for(int X=0;X<vsize;X++){
int LL=X+1,RR=vsize-1;
while(LL<=RR){
if(cnt==vsize-1)break;
int p=getnxt(X,LL,RR);
if(p==-1){
for(int i=LL;i<=RR;i++){
cur.push_back(edge(X,i));
}break;
}
else{
for(int i=LL;i<p;i++){
cur.push_back(edge(X,i));
}
++cnt;
//cout<<X<<" "<<p<<endl;
tree.push_back(edge(X,p));
LL=p+1;
}
}
}
for(size_t i=0;i<tree.size();i++){
int u=tree[i].first,v=tree[i].second;
adde(u,v);adde(v,u);
G[u][v]=G[v][u]=1;
}
dfs(0,0);
for(int i=0;i<vsize;i++){
for(int j=i+1;j<vsize;j++)if(col[i]^col[j]){
if(G[i][j]==0)chksecond.push_back(edge(i,j));
}
}
for(size_t i=0;i<tree.size();i++){
chksecond.push_back(tree[i]);
bool re=query(chksecond);
if(re==1)return ret;
chksecond.pop_back();
}
for(int i=0;i<vsize;i++)if(col[i]){
ret.push_back(i);
}
return ret;
}