码迷,mamicode.com
首页 > 其他好文 > 详细

bzoj-2278 Garbage

时间:2015-09-23 11:51:08      阅读:236      评论:0      收藏:0      [点我收藏+]

标签:bzoj   poi   欧拉回路   dfs   

题意:

给出一个n个点m条边无向图,每个边有一个01状态;

现在可以选择一些环,使环上的所有状态取反;

给出初始与结束状态,求一个方案;

1<=n<=100000,1<=m<=1000000;


题解:

做完这题深刻的体会到自己的too young too naive;

首先有一个性质,如果有解,一定存在一种方案使选择的所有环不重复经过一条边;

这个性质也说明了,所有不需要更改的边是可以忽视的;

因为如果将其选了偶数次,也可以构造出另一种方案不选它;

所以问题转化成从原图选出状态不同的边,然后求多个欧拉回路覆盖所有边的方案;

无向图存在欧拉回路的条件是结点的度都是偶数;

判掉NIE的情况之后,开始求图的欧拉回路。。

然后我写个搜索就被卡了!并不是常数的问题而是复杂度不对;

首先大多数人的图都是用链式前向星存对吧;

那么每次搜到一个点遍历一遍边表找没被删除的边的时候。。

这就给了丧心病狂的人可乘之机!

给出一个是:技术分享

这个样子的菊花图,5W个褶,然后扫着扫着就超时了;

所以我们要更新前向星中的head[x],每次删除的边都是最上面的,只要将head[x]赋为某个next就行了;

时间复杂度O(n+m),读入较大,输出较大,常数较大;

在连续几道题垫底的节奏下终于有一道题Rank1啦好开心;


代码:


#include<cctype>
#include<vector>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define N 131072
#define M 2100000
#define LEN 1<<20
using namespace std;
int to[M],next[M],head[N],ce=1;
int du[N];
bool ban[M],vis[N];
int cnt;
char getc()
{
	static char *S,*T,buf[LEN];
	if(S==T)
	{
		T=(S=buf)+fread(buf,1,LEN,stdin);
		if(S==T)
			return EOF;
	}
	return *S++;
}
int read()
{
	static char ch;
	static int D;
	while(!isdigit(ch=getc()));
	for(D=ch-'0';isdigit(ch=getc());)
		D=D*10+ch-'0';
	return D;
}
namespace ans
{
	int val[M],next[M],head[N<<1],size[N<<1],ce;
	void add(int x,int y)
	{
		size[x]++;
		val[++ce]=y;
		next[ce]=head[x];
		head[x]=ce;
	}
}
void add(int x,int y)
{
	to[++ce]=y;
	next[ce]=head[x];
	head[x]=ce;
}
int dfs(int x,int pre)
{
	vis[x]=1;
	int i,y;
	for(i=head[x];i;i=next[i])
	{
		if(ban[i]||(i^1)==pre)	continue;
		if(!vis[to[i]])
		{
			y=dfs(to[i],i);
			ans::add(cnt,x);
			ban[i]=ban[i^1]=1;
			head[x]=next[i];
			if(x!=y)
			{
				vis[x]=0;
				return y;
			}
		}
		else
		{
			cnt++;
			ans::add(cnt,to[i]);
			ans::add(cnt,x);
			ban[i]=ban[i^1]=1;
			head[x]=next[i];
			vis[x]=0;
			return to[i];
		}
	}
	vis[x]=0;
	return 0;
}
int main()
{
	int n,m,i,j,k,x,y,z,w;
	n=read(),m=read();
	for(i=1;i<=m;i++)
	{
		x=read(),y=read(),z=read(),w=read();
		if(z!=w)
			add(x,y),add(y,x),du[x]++,du[y]++;
	}
	for(i=1;i<=n;i++)
	{
		if(du[i]&1)
		{
			puts("NIE");
			return 0;
		}
	}
	for(i=1;i<=n;i++)
	{
		if(head[i])
			dfs(i,0);
	}
	printf("%d\n",cnt);
	for(i=1;i<=cnt;i++)
	{
		printf("%d ",ans::size[i]-1);
		for(j=ans::head[i];j;j=ans::next[j])
		{
			printf("%d ",ans::val[j]);
		}
		printf("\n");
	}
	return 0;
}



bzoj-2278 Garbage

标签:bzoj   poi   欧拉回路   dfs   

原文地址:http://blog.csdn.net/ww140142/article/details/48676373

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!