[TCO2009]NumberGraph
题意:给你一些带权的节点和一个正整数集合$S$,$S$中每一个数的二进制后缀$0$个数相同,节点$x$的权值为$v_x$,如果对于$x,y$存在$t\in S$使得$|v_x-v_y|=t$,那么连边$(x,y)$,现在要找出一个最大的子图使得子图中的节点两两最短距离$\leq2$
第一次用TC客户端上的Arena,特别开心==
如果$S$中每个数末尾有$k$个$0$,那么一条边的两个端点的权值的第$k+1$位必定不同,所以这个图是二分图
接下来相当于是要在二分图的两部分中分别找一个非空点集,使得两个集合中的点两两有边相连,对两部间的边取补后问题变为两两无边相连
因为要求非空所以不能直接跑最大独立集,考虑枚举一对不相邻的,分属二分图两部的节点,硬点他们必须被选,删掉它们和与之相连的边,对剩下的点跑最大独立集即可
#include<vector>
#include<string>
#include<sstream>
#include<algorithm>
#include<string.h>
using namespace std;
const int inf=2147483647;
int lowbit(int x){return x&-x;}
int abs(int x){return x>0?x:-x;}
string str;
int h[90],nex[5010],to[5010],cap[5010],M,S,T;
void ins(int a,int b,int c){
M++;
to[M]=b;
cap[M]=c;
nex[M]=h[a];
h[a]=M;
}
void add(int a,int b,int c){
ins(a,b,c);
ins(b,a,0);
}
int dis[90],q[90];
bool bfs(){
int head,tail,x,i;
memset(dis,-1,sizeof(dis));
head=tail=1;
q[1]=S;
dis[S]=0;
while(head<=tail){
x=q[head++];
for(i=h[x];i;i=nex[i]){
if(cap[i]&&dis[to[i]]==-1){
dis[to[i]]=dis[x]+1;
if(to[i]==T)return 1;
q[++tail]=to[i];
}
}
}
return 0;
}
int cur[90];
int dfs(int x,int flow){
if(x==T)return flow;
int us=0,i,t;
for(i=cur[x];i&&flow;i=nex[i]){
if(cap[i]&&dis[to[i]]==dis[x]+1){
t=dfs(to[i],min(flow,cap[i]));
cap[i]-=t;
cap[i^1]+=t;
us+=t;
flow-=t;
if(cap[i])cur[x]=i;
}
}
if(us==0)dis[x]=-1;
return us;
}
int dicnic(){
int ans=0;
while(bfs()){
memcpy(cur,h,sizeof(h));
ans+=dfs(S,inf);
}
return ans;
}
bool g[90][90];
int v1[90],v2[90],d[90],n1,n2,lw,cnt;
int gao(int x,int y){
int i,j,sum;
cnt++;
d[x]=cnt;
for(i=1;i<=n2;i++){
if(g[x][i])d[i+n1]=cnt;
}
d[y+n1]=cnt;
for(i=1;i<=n1;i++){
if(g[i][y])d[i]=cnt;
}
memset(h,0,sizeof(h));
M=1;
sum=0;
for(i=1;i<=n1;i++){
if(d[i]!=cnt){
add(S,i,1);
sum++;
}
}
for(i=n1+1;i<=n1+n2;i++){
if(d[i]!=cnt){
add(i,T,1);
sum++;
}
}
for(i=1;i<=n1;i++){
if(d[i]!=cnt){
for(j=n1+1;j<=n1+n2;j++){
if(g[i][j-n1]&&d[j]!=cnt){
add(i,j,1);
}
}
}
}
return sum-dicnic()+2;
}
class NumberGraph{
public:
int largestSet(vector<string>gs,vector<int>js){
int x,i,j,k,ans;
bool flag;
str="";
for(i=0;i<(int)gs.size();i++)str+=gs[i];
istringstream cin(str);
lw=lowbit(js[0]);
n1=n2=0;
while(cin>>x)(x&lw?v1[++n1]:v2[++n2])=x;
S=n1+n2+1;
T=S+1;
for(i=1;i<=n1;i++){
for(j=1;j<=n2;j++){
flag=1;
for(k=0;k<(int)js.size();k++){
if(abs(v1[i]-v2[j])==js[k]){
flag=0;
break;
}
}
g[i][j]=flag;
}
}
ans=1;
for(i=1;i<=n1;i++){
for(j=1;j<=n2;j++){
if(!g[i][j])ans=max(ans,gao(i,j));
}
}
return ans;
}
};
/*
int main(){
NumberGraph g;
vector<string>vs;
vector<int>vi;
string s;
int x;
ostringstream os;
scanf("%d",&x);
while(x){
os<<x<<' ';
scanf("%d",&x);
}
vs.push_back(os.str());
scanf("%d",&x);
while(x){
vi.push_back(x);
scanf("%d",&x);
}
printf("%d",g.largestSet(vs,vi));
}
*/
[TCO2009]NumberGraph的更多相关文章
随机推荐
- Spring Session加Redis(山东数漫江湖)
session是一个非常常见的概念.session的作用是为了辅助http协议,因为http是本身是一个无状态协议.为了记录用户的状态,session机制就应运而生了.同时session也是一个非常老 ...
- 01背包入门 dp
题目引入: 有n个重量和价值分别为Wi,Vi的物品.从这些物品中挑选出总重量不超过W的物品,求所有挑选方案中的价值总和的最大值. 分析: 首先,我们用最普通的方法,针对每个物品是否放入背包进行搜索. ...
- elementui raido 单选框 循环渲染加:key
<el-radio-group v-model="adminRole"> <el-radio v-for="item in adminRoles&quo ...
- Angular2.0 基础: User Input
1.Angular 2.0 中的变量 对输入值的获取,我们可以通过$event 来获取,也可以通过变量来获取. template: ` <input (keyup)="onKey($e ...
- 一个基于时间注入的perl小脚本
use strict; use warnings; use LWP::Simple; my %table_and_leng; ;;$count++){ #print "Test Table: ...
- Python3 嵌套函数
嵌套函数: 函数体内用def定义函数 注意:函数体中调用其他函数不算嵌套函数,只能是函数的调用 简单的嵌套函数: 输出结果:
- dump_stack 实现分析【转】
转自:http://kernel.meizu.com/2017/03/18-40-19-dump_stack.html 1 简介 说起 dump_stack() ,相信从事 Linux 内核或者驱动相 ...
- ue4.3正式版源码链接
ue4.3正式版源码链接 http://tieba.baidu.com/p/3170253742
- mongodb 学习笔记--- 基础知识
1.mongodb的安装 (1) mac使用brew 安装就好 brew install mongodb (2) mkdir /data/db 作为mongodb默认的数据目录 并 sudo chow ...
- 转 白话解析:一致性哈希算法 consistent hashing
摘要: 本文首先以一个经典的分布式缓存的应用场景为铺垫,在了解了这个应用场景之后,生动而又不失风趣地介绍了一致性哈希算法,同时也明确给出了一致性哈希算法的优点.存在的问题及其解决办法. 声明与致谢: ...