bzoj3440: 傳球遊戲

這不傻逼題嗎!

一開始連題目都被讀懂。。。

第1類人,順着傳來的方向傳給下一個人。
第2類人,逆着傳來的方向傳給上一個人。
第3類人,順着傳來的方向傳給下面第二個人。
第4類人,逆着傳來的方向傳給上面第二個人。
不知是從哪個人開始傳,及開始傳的方向,求有哪些人無論如何最多只能碰到一次球
然後很容易想到拆點,然後找環,可是不止有這種情況,可以從1號順時針走到2號順時針再走到1號逆時針,1號也算走了2次。。。

於是刪程序繼續碼碼碼,終於A了。


#include<iostream>
#include<cstdio>
#define N 1000005
using namespace std;
int LY[5]={0,1,-1,2,-2},Ans;
int n,a[N],fl[N],ok[N],fa[N],rd[N],l,first[N],F[N],flag[N];
struct E{int to,next;}e[N*2];
int go(int x,int y)
{
	x+=y;
	if (x<=0) x+=n;
	if (x>n) x-=n;
	return x+(y>0?0:n);
}
void link(int x,int y)
{
	e[++l]=(E){x,first[y]};first[y]=l;
}
void huan(int x)
{
	if (rd[x]!=0||flag[x]) return;
	flag[x]=1;rd[fa[x]]--;huan(fa[x]);
}
void dfs(int x,int y)
{
	fl[x]=y;
	if (fl[(x>n)?x-n:x+n]==y) ok[x]=1;
	for (int i=first[x];i;i=e[i].next)
		if (!fl[e[i].to])
			dfs(e[i].to,y);
	fl[x]=0;
}
int main()
{
	scanf("%d",&n);
	for (int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	for (int i=1;i<=n;i++)
	{
		int y;
		y=go(i,LY[a[i]]);link(i,y);rd[y]++;fa[i]=y;
		y=go(i,-LY[a[i]]);link(i+n,y);rd[y]++;fa[i+n]=y;
	}
	for (int i=1;i<=n*2;i++)
		huan(i);
	for (int i=1;i<=n*2;i++)
		if (rd[i]) 
		{
			ok[i]=1;F[i]=i;rd[i]=0;
			for (int j=fa[i];j!=i;j=fa[j])
			{
				ok[j]=1;F[j]=i;rd[j]=0;
				for (int k=first[j];k;k=e[k].next)
					if (F[e[k].to]!=i) link(i,e[k].to);
			}
			fa[i]=0;
			dfs(i,i);
		}
	for (int i=1;i<=n;i++)
		if (!ok[i]&&!ok[i+n]) Ans++;
	printf("%d\n",Ans);
	for (int i=1;i<=n;i++)
		if (!ok[i]&&!ok[i+n]) printf("%d ",i);
}

看着同學都在刷線段樹,TAT~~~
發佈了93 篇原創文章 · 獲贊 24 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章