HZOJ 連連看

考場幾乎想到了正解,然而我也不知道當時在想啥,在沒有證僞的狀況下只是以爲沒法實現就否了……node

最後打的好象是達哥說的O(4*15*n*m),複雜度不是很會證反正T成了暴力……ios


 

題解:

對於測試點8,9,10:bfs每一個0的聯通塊,若是聯通塊邊緣某累方塊出現了x個,那麼貢獻爲x*(x-1)/2。注意去掉既相鄰又處於同一聯通塊的貢獻。因爲這些測試點的性質,統計出來的答案是正確的。數組

推廣到通常狀況,上面的結論不是徹底適用。測試

考慮上面結論會錯在什麼地方,當兩個方塊同時屬於多個0的聯通塊時會被算重,考慮容斥。(因爲沒有想到複雜度合適的實現方法考場止步於此)spa

考慮給每一個0的聯通塊編號,爲了方便起見,設相鄰兩個同類方塊之間也有一個0聯通塊。blog

首先bfs求出每一個非0點屬於的0聯通塊,複雜度$O(nm)$。ci

對於每類方塊,求出f1[i]表示處於i聯通塊的個數,f2[i][j]表示處於i,j(能夠有其餘)的個數,f3[][][],f4[][][][]同理。string

以後就能夠奇加偶減統計答案。hash

然而數組並開不了那麼大,考慮Hash_map.it

因爲hash結構體並非很好弄,因而我用了map,更容易理解,代碼複雜度也更低一些。

因此下面的代碼極易被卡常。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<map>
#define int LL
#define pair pair<int,int>
#define fir first
#define sec second
#define MP(a,b) make_pair(a,b)
#define LL long long
#define s1 (a.a<b.a)
#define s2 (a.b<b.b)
#define s3 (a.c<b.c)
#define s4 (a.d<b.d)
#define s5 (a.s<b.s)
#define d1 (a.a==b.a)
#define d2 (a.b==b.b)
#define d3 (a.c==b.c)
#define d4 (a.d==b.d)
#define d5 (a.s==b.s)
using namespace std;
struct node1{int a,s;friend bool operator < (node1 a,node1 b){return d1?s5:s1;}};
struct node2{int a,b,s;friend bool operator < (node2 a,node2 b){return d1?(d2?s5:s2):s1;}};
struct node3{int a,b,c,s;friend bool operator < (node3 a,node3 b){return d1?(d2?(d3?s5:s3):s2):s1;}};
struct node4{int a,b,c,d,s;friend bool operator < (node4 a,node4 b){return d1?(d2?(d3?(d4?s5:s4):s3):s2):s1;}};
map<node1,int>mp1;
map<node2,int>mp2;
map<node3,int>mp3;
map<node4,int>mp4;
int n,m,k,mp[1010][1010];
int bel[1010][1010],cnt;
int t[1000010];
bool v[1010][1010];
int ix[5]={0,1,-1,0, 0};
int iy[5]={0,0, 0,1,-1};
vector<int> be[1010][1010];

bool is(int x,int y,int sor){return x>0&&x<=n&&y>0&&y<=m&&mp[x][y]==sor;}
bool ok(int x,int y){return x>0&&x<=n&&y>0&&y<=m&&mp[x][y]==0;}
void bfs(int nx,int ny)
{
	bel[nx][ny]=cnt;
	queue<pair >q;q.push(MP(nx,ny));
	while(!q.empty())
	{
		int x=q.front().fir,y=q.front().sec;q.pop();
		for(int i=1;i<=4;i++)
		{	
			int tx=x+ix[i],ty=y+iy[i];
			if(ok(tx,ty)&&!bel[tx][ty])q.push(MP(tx,ty)),bel[tx][ty]=cnt;
			else if(tx>0&&tx<=n&&ty>0&&ty<=m&&mp[tx][ty])be[tx][ty].push_back(cnt);
		}
	}
}
signed main()
{
//	freopen("ex_link3.in","r",stdin);
//	freopen("in.txt","r",stdin);
//	freopen("1.out","w",stdout);
	
	cin>>n>>m>>k;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
			cin>>mp[i][j];
	
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		if(!mp[i][j]&&!bel[i][j])++cnt,bfs(i,j);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			if(mp[i][j]&&is(i+1,j,mp[i][j]))be[i][j].push_back(++cnt),be[i+1][j].push_back(cnt);
			if(mp[i][j]&&is(i,j+1,mp[i][j]))be[i][j].push_back(++cnt),be[i][j+1].push_back(cnt);
		}
		
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		{
			sort(be[i][j].begin(),be[i][j].end());
			int t=unique(be[i][j].begin(),be[i][j].end())-be[i][j].begin();
			while(be[i][j].size()>t)be[i][j].pop_back();
		}
	
	for(int i=1;i<=n;i++)
		for(int j=1;j<=m;j++)
		if(mp[i][j])
		{
			sort(be[i][j].begin(),be[i][j].end());int siz=be[i][j].size();
			if(siz>=1){for(int k=0;k<siz;k++)mp1[(node1){be[i][j][k],mp[i][j]}]++;}
			if(siz>=2){for(int k=0;k<siz;k++)for(int l=k+1;l<siz;l++)mp2[(node2){be[i][j][k],be[i][j][l],mp[i][j]}]++;}
			if(siz>=3){for(int k=0;k<siz;k++)for(int l=k+1;l<siz;l++)for(int r=l+1;r<siz;r++)
				mp3[(node3){be[i][j][k],be[i][j][l],be[i][j][r],mp[i][j]}]++;}
			if(siz>=4){mp4[(node4){be[i][j][0],be[i][j][1],be[i][j][2],be[i][j][3],mp[i][j]}]++;}
		}
	map<node1,int>::iterator it1;
	map<node2,int>::iterator it2;
	map<node3,int>::iterator it3;
	map<node4,int>::iterator it4;
	LL ans=0;
	for(it1=mp1.begin();it1!=mp1.end();it1++)ans+=it1->second*(it1->second-1)/2;
	for(it2=mp2.begin();it2!=mp2.end();it2++)ans-=it2->second*(it2->second-1)/2;
	for(it3=mp3.begin();it3!=mp3.end();it3++)ans+=it3->second*(it3->second-1)/2;
	for(it4=mp4.begin();it4!=mp4.end();it4++)ans-=it4->second*(it4->second-1)/2;
	printf("%lld\n",ans);
}
	
相關文章
相關標籤/搜索