[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的更多相关文章
随机推荐
- python dlib 面部轮廓实时检测
1.dlib 实现动态人脸检测及面部轮廓检测 模型下载连接 : http://dlib.net/files/ # coding:utf-8 import cv2 import os import dl ...
- 首行缩进css
html首行缩进2字符,可以使用CSS属性中的[text-indent]进行设置. 设置代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1 ...
- centos_7.1.1503_src_1
http://vault.centos.org/7.1.1503/os/Source/SPackages/ 389-ds-base-1.3.3.1-13.el7.src.rpm 31-Mar-2015 ...
- 压缩LDF档
--压缩LDF档 USE VoucherServer; GO -- Truncate the log by changing the database recovery model to SIMPLE ...
- C C++ 常被人问的问题分析
正文 - 开始了, 直接扯淡 以下都是自己面试中遇到的常见的问题.如有不妥的地方就当见笑了. 哈哈 1. 谈谈你们服务器的架构吧. 分析: 假如这是第一个问题, 你可以走了. 可能各方面原因他不想 ...
- caffe solver.prototxt 生成
from caffe.proto import caffe_pb2 s = caffe_pb2.SolverParameter() path='/home/xxx/data/' solver_file ...
- C++ 流操作符重载函数
1. 问题 在C++中,在进行输入输出操作时,我们首先会想到用cout, cin这两个库操作语句来实现,比如 cout << 8 << "hello world!&q ...
- python基础(1)---python简介
一.python简介 Python是著名的“龟叔”Guido van Rossum在1989年圣诞节期间,为了打发无聊的圣诞节而编写的一个编程语言.目前Python已经成为实际上除了中国最流行的开发语 ...
- [Android] 按钮单击事件的五种写法
在平时学习安卓的过程中,不论是看视频还是看博客,我发现每个人对代码的写法都有不同的偏好,比较明显的就是对控件响应事件的写法的不同.所以我想把这些写法总结一下,比较下各种写法的优劣,希望可以让自己可以灵 ...
- .net 多播委托的使用方法以及场景,更简单的观察者模式
首先来说一下什么是多播委托 多播委托就是在委托里定义一个或者多个方法的一个集合 使用方法: public Action actList; //添加方法 public void AddActionMet ...