题意:给你一些带权的节点和一个正整数集合$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的更多相关文章

随机推荐

  1. [Unity]扩展Hierachry的右键菜单

    游戏制作到一定阶段后,一定会出现一些GameObject的"模板".比如一个敌人一定会有一个"Enemy Behaviour"."Box Collid ...

  2. js_setCookie,getCookie和checkcookie函数

    随便说说: cookie和sessionStrong,localStrong在web应用中都有一种存储的功能,也就是说可以把一些数据记录在浏览器.cookie和后两者的主要区别 是cookie是和后端 ...

  3. 【shell】shell中各种括号的作用()、(())、[]、[[]]、{}

    一.小括号,圆括号() 1.单小括号 ()    ①命令组.括号中的命令将会新开一个子shell顺序执行,所以括号中的变量不能够被脚本余下的部分使用.括号中多个命令之间用分号隔开,最后一个命令可以没有 ...

  4. socket编程中write、read和send、recv之间的区别~转载

    socket编程中write.read和send.recv之间的区别   http://blog.csdn.net/petershina/article/details/7946615 一旦,我们建立 ...

  5. js/jq 键盘上下左右回车按键

    js判断上下左右回车按键: document.onkeydown=function(e){ e=window.event||e; switch(e.keyCode){ case 37: //左键 co ...

  6. C++学习之路(五):复制构造函数与赋值运算符重载

    之前没有细想过两者的区别,今天对此进行简要记录,后续完善补充. 复制构造函数是在类对象被创建时调用的,但是赋值运算符是被已经存在的对象调用完成赋值操作. 复制构造函数只在对象实例化时才被调用,即在复制 ...

  7. io多路复用-select()

    参照<Unix网络编程>相关章节内容,实现了一个简单的单线程IO多路复用服务器与客户端. 普通迭代服务器,由于执行recvfrom则会发生阻塞,直到客户端发送数据并正确接收后才能够返回,一 ...

  8. thread线程栈size及局部变量最大可分配size【转】

    转自:http://blog.csdn.net/sunny04/article/details/46805261 版权声明:本文为博主原创文章,未经博主允许不得转载. 进程是操作系统的最小资源管理单元 ...

  9. linux dpm机制分析(上)【转】

    转自:http://blog.csdn.net/lixiaojie1012/article/details/23707681 1      DPM介绍 1.1        Dpm:  设备电源管理, ...

  10. .net设置浏览器的文本模式

    这段时间做个项目,做的时候因为之前习惯了Google的调试方式,所以就一直在google上面调试,今天项目成员大家的部分要整合,就放到ie8下面测试,但是遇到一个问题,就是用ie打开之后文本模式一直是 ...